我想定义一个对象的类型,但让typescript推断键,并且没有那么多的开销来创建和维护所有键的UnionType。
键入一个对象将允许所有字符串作为键:
const elementsTyped: {
[key: string]: { nodes: number, symmetric?: boolean }
} = {
square: { nodes: 4, symmetric: true },
triangle: { nodes: 3 }
}
function isSymmetric(elementType: keyof typeof elementsTyped): boolean {
return elementsTyped[elementType].symmetric;
}
isSymmetric('asdf'); // works but shouldn't
推断整个对象将显示错误,并允许所有类型的值:
const elementsInferred = {
square: { nodes: 4, symmetric: true },
triangle: { nodes: 3 },
line: { nodes: 2, notSymmetric: false /* don't want that to be possible */ }
}
function isSymmetric(elementType: keyof typeof elementsInferred): boolean {
return elementsInferred[elementType].symmetric;
// Property 'symmetric' does not exist on type '{ nodes: number; }'.
}
我得到的最接近的结果是这样的,但它不想像那样维护密钥集:
type ElementTypes = 'square' | 'triangle'; // don't want to maintain that :(
const elementsTyped: {
[key in ElementTypes]: { nodes: number, symmetric?: boolean }
} = {
square: { nodes: 4, symmetric: true },
triangle: { nodes: 3 },
lines: { nodes: 2, notSymmetric: false } // 'lines' does not exist in type ...
// if I add lines to the ElementTypes as expected => 'notSymmetric' does not exist in type { nodes: number, symmetric?: boolean }
}
function isSymmetric(elementType: keyof typeof elementsTyped): boolean {
return elementsTyped[elementType].symmetric;
}
isSymmetric('asdf'); // Error: Argument of type '"asdf"' is not assignable to parameter of type '"square" | "triangle"'.
有没有更好的方法来定义对象而不维护键集?
3条答案
按热度按时间h79rfbju1#
因此,您需要推断键但限制值类型的东西,并使用多余的属性检查来禁止额外的属性。我认为获得这种行为的最简单方法是引入一个helper函数:
这个辅助函数从
et
的Map类型推断T
的类型。现在你可以这样使用它:结果
elementsTyped
的类型(一旦修复错误)将具有推断的键square
、triangle
和line
,值为ElementType
。希望对你有用。祝你好运!
oknrviil2#
TypeScript >=4.9.0
TypeScript
4.9.0
添加了satisfies
关键字,可用于在推断键时约束对象的值。TypeScript <4.9.0
中间函数可用于在推断键时约束对象的值。
klsxnrf13#
另一个更简单的解决方案涉及使用
enum
而不是复杂的TS类型继承:这个解决方案可读性更强,使用基本类型和
enum
。唯一的缺点是enum
应该与一个字符串值配对,以便在自动完成中可读。