我有一个泛型函数,它以数组为参数,我想构造由数组传递的泛型类型。这个函数工作得很好,但是我想添加一个类型来检查数组键是否构成泛型类型,如果不是,它应该抛出一个Typescript错误。
接口interface OutputType {
id: string;
name: string;
age: number;
}
interface ArrayType {
key: string;
value: any;
}
的泛型函数function TestType<T>(array: ArrayType[]): T {
let newObj = {} as T;
array.forEach((arrayItem) => {
newObj[arrayItem.key as keyof T] = arrayItem.value;
});
return newObj;
}
这应该导致TS **ERROR **,因为它缺少'id'属性
const array = [
{
key: "name",
value: "TestName",
},
{
key: "age",
value: 12,
},
] as ArrayType[];
这会清除TS错误
const array = [
{
key: "id",
value: "1",
},
{
key: "name",
value: "TestName",
},
{
key: "age",
value: 12,
},
] as ArrayType[];
下面是完整的示例代码:https://playcode.io/1019051
当我尝试为数组参数实现自定义类型时,我目前卡住了。
我想创建一个自定义类型来检查传入的数组,并根据泛型类型属性验证
这绝对是一个棘手的问题。要解决这个问题,您必须采用泛型类型T
并从中生成所有有效的数组排列。
给定类型T
interface OutputType {
id: string;
name: string;
age: number;
}
有效数组的并集如下所示:
type Permutations = [{
key: "id";
value: string;
}, {
key: "name";
value: string;
}, {
key: "age";
value: number;
}] | [{
key: "id";
value: string;
}, {
key: "age";
value: number;
}, {
key: "name";
value: string;
}] | [...] | [...] | [...] | ...
可以使用泛型派生出这样的联合。
type CreatePermutations<
T extends Record<string, any>,
K extends keyof T = keyof T,
C extends keyof T = K
> =
[K] extends [never]
? []
: K extends K
? [{ key: K, value: T[K] }, ...CreatePermutations<T, Exclude<C, K>>]
: never
,并在函数定义中使用此泛型类型。
function TestType<
T extends Record<string, any>
>(array: CreatePermutations<T> & ArrayType[]): T {
let newObj = {} as T;
array.forEach((arrayItem) => {
newObj[arrayItem.key as keyof T] = arrayItem.value;
});
return newObj;
}
当给定的函数输入与基于给定泛型T
计算的排列不匹配时,将导致编译时错误。
// Error: Source has 2 element(s) but target requires 3.(2345)
TestType<OutputType>([
{
key: "name",
value: "TestName",
},
{
key: "age",
value: 12,
},
])
TestType<OutputType>([
{
key: "id",
value: "1",
},
{
key: "name",
value: "TestName",
},
{
key: "age",
value: 12,
},
])
这个实现的问题是它是组合爆炸。对于具有更多属性的对象,计算所有可能组合的并集将变得非常昂贵。
游乐场