假设我有以下对象:
const arrayOfDifferentComponents: HowDoITypeThis = [
{
component: ComponentOne, // no error, keys and value types match
inputs: {
key1: "foo"
key2: 1
}
},
{
component: ComponentTwo, // error, key2 should be boolean
inputs: {
key1: ["foo"]
key2: 1
}
}
]
class ComponentOne {
key1!: string;
key2!: number;
}
class ComponentTwo {
key1!: Array<string>;
key2!: boolean;
}
是否可以在没有泛型的情况下写入类型HowDoITypeThis
,使得第一个数组项中的inputs
只允许ComponentOne
的键,而第二个数组项的inputs
只允许ComponentTwo
的键?
为了澄清,我希望这种类型能够与动态数量的组件和组件类型一起使用。
如果可用类型已知
您可以使用映射类型来创建可能配对的并集,但这有一些限制。它将使用动态数量的组件/类型对,而不是未知数字。
当您通过映射类型创建并集时,基本上您要做的是创建一个键值对象类型,然后获取所有值的并集。因此,密钥被丢弃,但我们在某个时刻需要某种密钥,以便进行从ComponentOne
到{component: ComponentOne; inputs: React.ComponentProps<ComponentOne>}
的映射。在这种情况下,我很难确定关键是什么,因为我没有看到任何判别式。
(附带说明:我发现你的命名很混乱,因为你的ComponentOne
是道具类型,而不是组件类型,所以我使用的名称更清晰。(
如果你定义这样的地图:
type PropTypes = {
one: ComponentOneProps;
two: ComponentTwoProps;
}
然后你可以使用这样的映射类型:
type ComponentAndProps = {
[K in keyof PropTypes]: {
component: React.ComponentType<PropTypes[K]>;
inputs: PropTypes[K];
}
}[keyof PropTypes];
这给了你所有有效配对的并集:
type ComponentAndProps = {
component: React.ComponentType<ComponentOneProps>;
inputs: ComponentOneProps;
} | {
component: React.ComponentType<ComponentTwoProps>;
inputs: ComponentTwoProps;
}
您的HowDoITypeThis
是一个数组ComponentAndProps[]
。如果尝试将ComponentOneProps
分配给ComponentTwo
组件,则会出现一个大的红色错误。
TypeScript游乐场链接
如果可用类型未知
如果您希望数组接受任何类型的组件,但要求component
和input
属性匹配,则需要一种不同的方法。这确实需要泛型。它还要求您通过函数创建arrayOfDifferentComponents
,因为我们不能说出它的特定类型。我们需要推断它的泛型,并检查所提供的数组是否适用于该泛型。
您可以创建一个映射类型,从道具类型的元组映射到component
/inputs
对的元组:
type MapToPairing<T> = {
[K in keyof T]: {
component: React.ComponentType<T[K]>;
inputs: T[K];
}
}
并使用身份函数来确保您的数组有效:
const createComponentArray = <T extends {}[]>(array: MapToPairing<T>) => array;
当数组中包含component
和inputs
属性不匹配的元素时,确实会出现预期的错误。
TypeScript游乐场链接
您基本上拥有它:
type HowDoITypeThis = [
{
component: ComponentOne,
inputs: {
someKeyOfComponentOne: ComponentOne[someKeyOfComponentOne]
}
},
{
component: ComponentTwo,
inputs: {
someKeyOfComponentTwo: ComponentTwo[someKeyOfComponentTwo]
}
}
]
您可以使用类型脚本元组,如
type HowDoITypeThis = [
{
component: ComponentOne;
inputs: {
someKeyOfComponentOne: ComponentInputA;
};
},
{
component: ComponentTwo;
inputs: {
someKeyOfComponentTwo: ComponentInputB;
};
}
]
当然你也可以做这个
interface MyGenericA<T, U> {
component: T;
inputs: U;
}
type HowDoITypeThis = [
MyGenericA<ComponentOne, YourInputTypeA>,
MyGenericA<ComponentTwo, YourInputTypeB>
]