首先:这是我第一次制作CodeSandbox来创建一个简化的例子。欢迎任何有关如何改进的建议!
问题:
我想展示动物的事实。有些事实是所有动物共有的,而另一些则是特定于动物的。在我的主要组件中App
,我还不知道类型。所以我想把它保持在通用Animal
级别。在我的主要组件中发生了一些魔法(几乎只是一个 API 调用),现在我知道类型了。这会导致我渲染一个特定的Animal
组件。这些特定组件本身具有更通用的组件,当然还有一些特定的动物数据。
现在我无法思考如何使用typescript正确地做到这一点。代码和框应该清除一切:正如你所看到的,编译器给我带来了困难,因为类型Animal
未知。没错。我该如何解决这个问题?我仍在学习typescript,所以如果我对此的一般方法是不明智的,我很乐意提供有关如何构建它的建议。
对于喜欢这里代码类型的人,这里是:
一般应用程序:
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;
};