假设我有以下对象:
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
的键?
澄清一下,我希望这种类型能够处理动态数量的组件和组件类型。
最佳答案
您可以使用映射类型来创建可能配对的并集,但这有一些限制。它将使用动态数量的组件/类型对,但不适用于未知数量。
当您通过映射类型创建联合时,基本上您所做的就是创建一个键值对象类型,然后获取所有值的联合。所以 key 被丢弃了,但我们在某些时候需要某种 key 才能从 ComponentOne
进行映射。至 {component: ComponentOne; inputs: React.ComponentProps<ComponentOne>}
.由于我没有看到任何类型的判别式,因此我正在努力解决这种情况下的关键问题。
(旁注:我发现您的命名令人困惑,因为您的 ComponentOne
是 props 类型而不是组件类型,所以我使用的名称更清晰。)
如果你像这样定义某种 map :
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 Playground Link
如果你想让你的数组接受任何类型的组件,你需要一个不同的方法,但强制component
和 input
属性匹配。这确实需要泛型。它还要求您创建 arrayOfDifferentComponents
通过一个函数,因为我们不能说出它的具体类型。我们需要推断它的泛型并检查所提供的数组对于该泛型是否正确。
您可以创建一个映射类型,将 prop 类型的元组映射到 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 Playground Link
https://stackoverflow.com/questions/67631215/