没有泛型的类型推理



假设我有以下对象:

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游乐场链接


如果可用类型未知

如果您希望数组接受任何类型的组件,但要求componentinput属性匹配,则需要一种不同的方法。这确实需要泛型。它还要求您通过函数创建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;

当数组中包含componentinputs属性不匹配的元素时,确实会出现预期的错误。

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>
]

最新更新