我正在尝试编写一个具有以下要求的函数:
示例:
const group = createGroup({
name: "group1",
items: {
key1: {
description: 'i1',
values: {
default: 'b',
north: 'n',
}
},
key2: {
description: 'i2',
values: {
default: 1,
south: 2,
}
}
}
});
此对象的输出是可以使用的对象。
console.log(group.key1) // based on current direction will return 'b' or 'n';
console.log(group.key2); // based on current location will return 1 or 2
// key1 is of type string, key2 is of type number
我完全可以使用它,但是我的目标是在不两次声明类型或泛型的情况下完全键入它,并避免用户扩展values属性。
这是我使用的类型:
type Direction = 'north' | 'south' | 'east' | 'west';
type GroupValuesRecord<T extends string, K> = Partial<Record<T, K>> & { default: K };
type ItemConfig = {
description: string;
values:
| GroupValuesRecord<Direction, string>
| GroupValuesRecord<Direction, number>
| GroupValuesRecord<Direction, boolean>;
};
type GroupItems = Record<string, ItemConfig>;
type GroupConfig<T extends GroupItems> = {
name: string
items: T
}
type OutputValue<T extends GroupItems> = { readonly [id in keyof T]: T[id]['values']['default'] };
function createGroup<T extends GroupItems>(config: GroupConfig<T>): OutputValue<T> {
// some implementation that involves define property
}
这种类型系统的唯一缺点是可以扩展每个项目而不会显示错误 例如。
const group = createGroup({
name: "group1",
items: {
key1: {
description: 'i1',
values: {
default: 'b',
north: 'n',
badValue: 'badValue' // this doesn't throw an error
}
},
自动填充也不适用于北部,南部等。
我猜它允许的原因是createGroup函数中的扩展泛型。有没有更好的方法来编写此函数?或一种将values属性类型锁定为仅允许Direction
TS游乐场Link
中的完整示例