【发布时间】:2021-06-03 12:59:48
【问题描述】:
首先:这是我第一次做 CodeSandbox 来创建一个简化的例子。欢迎就如何改进这一点提出任何建议!
问题:
我想介绍动物事实。有些事实是所有动物共有的,而另一些则是特定于动物的。在我的主要组件App 中,我还不知道类型。所以我想把它保持在通用的Animal 级别。在我的主要组件中发生了一些魔法(几乎只是一个 API 调用),现在我知道了类型。这会在我渲染一个特定的Animal 组件。这些特定组件本身具有更通用的组件,当然还有一些特定的动物数据。
现在,我无法完全理解如何使用 typescript 正确执行此操作。代码框应该把事情弄清楚:正如你所看到的,编译器让我很难过,因为类型 Animal 是未知的。没错。我该如何解决这个问题?我仍在学习打字稿,所以如果我对此的一般方法是不明智的,我很高兴就如何构建它提出建议。
Codesandbox to make it more understandable
对于那些更喜欢这里的代码类型的人,这里是:
通用应用:
export default function App() {
const [data, setData] = React.useState<TFact<Animal>>();
return (
<div className="App">
<h1>Hi there</h1>
{/* This is part of a switch case, I know at this point
what kind of animal to render */}
<Cat data={data} />
{/*<Dog data={data} />*/}
</div>
);
}
子组件的两个例子:
interface IProps {
data: TFact<TCat>;
}
const Cat = ({ data }: IProps) => {
return (
<div>
<GeneralChild data={data} />
Meow!
</div>
);
};
export default Cat;
第二个:
interface IProps {
data: TFact<TDog>;
}
const Dog = ({ data }: IProps) => {
return (
<div>
<GeneralChild data={data} />
Woof!
</div>
);
};
export default Dog;
一般孩子:
interface IProps {
data: TFact<Animal>;
}
const GeneralChild = ({ data: IProps }) => {
return (
<div>
Well I can be anything! And that is okay, because I only need the data
shared by all components!
</div>
);
};
export default GeneralChild;
最相关的是打字:
export type TFact<Animal extends TCat | TDog | TDuck> = {
name: string;
age: number;
animalSpecificDetails: Animal;
};
export type TCat = {
randomFact1: string;
randomFact2: string;
feelsLikeaGod: boolean;
};
export type TDog = {
randomFact1: string;
randomFact2: string;
alwaysLoyal: boolean;
};
export type TDuck = {
randomFact1: string;
randomFact2: string;
sound: string;
};
【问题讨论】:
-
从您的示例中,看起来
Animal并未实际定义。当Animal用作泛型时,我看到的唯一实例,即Animal extends TCat | TDog | TDuck。在这种情况下,没有实际定义,因为 Animal 被视为变量 (T)。这意味着它仅与该特定定义相关。您需要定义它(类型、接口或类)并将其导出以供其他文件使用。
标签: reactjs typescript generics typescript-generics