您可以将接口generic设置为columns
属性的类型,然后将相应的数组属性定义为适当长度的101.
为此,您需要一个类似TupLen<N extends number, V>
的实用程序类型,它将解析为一个长度为N
的元组,其中每个元素都是V
类型:
interface EquipmentSectionProps<N extends number> {
bgColor: "black" | "lightGrey";
columns: N;
category: string;
products: TupLen<N, string>;
productImages: TupLen<N, string>;
productReferals: TupLen<N, string>;
}
const good: EquipmentSectionProps<3> = {
bgColor: "black", category: "abc", columns: 3,
products: ["a", "b", "c"],
productImages: ["d", "e", "f"],
productReferals: ["g", "h", "i"]
};
const bad: EquipmentSectionProps<3> = {
bgColor: "black", category: "abc", columns: 3,
products: ["a", "b", "c"],
productImages: ["d", "e"], // error! 2 elements but requires 3
productReferals: ["g", "h", "i", "j"] // error! 4 elements but only allows 3.
};
但是TupLen<N, V>
中没有内置的,你必须自己写.一种方法是使用variadic tuple types作为tail-recursive conditional type:
type TupLen<N extends number, V = any, A extends V[] = []> =
number extends N ? V[] : N extends A['length'] ? A : TupLen<N, V, [...A, V]>;
type TestNumber4 = TupLen<4, number>;
// type TestNumber4 = [number, number, number, number]
type TestBoolean2 = TupLen<2, boolean>;
// type TestBoolean2 = [boolean, boolean]
此外,如果您不想编写两次列长度,如在const v: EquipmentSectionProps<3> = { columns: 3, ⋯}
中(一次用于类型参数,一次用于columns
属性),则可以从columns
属性的值向infer编写一个Helper函数作为泛型类型参数:
const equipmentSectionProps =
<N extends number>(esp: EquipmentSectionProps<N>) => esp;
const good = equipmentSectionProps({
bgColor: "black", category: "abc",
columns: 3,
products: ["a", "b", "c"],
productImages: ["d", "e", "f"],
productReferals: ["g", "h", "i"]
})
// const good: EquipmentSectionProps<3>
const bad = equipmentSectionProps({
bgColor: "black", category: "abc",
columns: 3,
products: ["a", "b", "c"],
productImages: ["d", "e"], // error,
// '[string, string]' is not '[string, string, string]'.
productReferals: ["g", "h", "i", "j"] // error,
// '[string, string, string, string]' is not '[string, string, string]'.
})
// const good: EquipmentSectionProps<3>
您无需显式写出EquipmentSectionProps<3>
即可获得相同的行为.
Playground link to code个