如何让 Typescript 推断对象的键但定义其值的类型? [英] How to make Typescript infer the keys of an object but define type of its value?
问题描述
我想定义一个对象的类型,但让 typescript 推断键,并且没有太多开销来创建和维护所有键的 UnionType.
I want to define the type of an object but let typescript infer the keys and don't have as much overhead to make and maintain a UnionType of all keys.
输入一个对象将允许所有字符串作为键:
Typing an object will allow all strings as keys:
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
推断整个对象将显示错误并允许所有类型的值:
Inferring the whole object will show an error and allows all kind of values:
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; }'.
}
我得到的最接近的是这个,但它不想维护这样的键集:
The closest I got was this, but it don't want to maintain the set of keys like that:
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"'.
有没有更好的方法来定义对象而不维护键集?
Is there a better way to define the object without maintaining the set of keys?
推荐答案
所以你想要推断键但限制值类型并使用 多余的属性检查 禁止额外的属性.我认为获得这种行为的最简单方法是引入一个辅助函数:
So you want something that infers keys but restricts the value types and uses excess property checking to disallow extra properties. I think the easiest way to get that behavior is to introduce a helper function:
// Let's give a name to this type
interface ElementType {
nodes: number,
symmetric?: boolean
}
// helper function which infers keys and restricts values to ElementType
const asElementTypes = <T>(et: { [K in keyof T]: ElementType }) => et;
这个辅助函数推断类型 T
来自 et
的映射类型.现在你可以像这样使用它:
This helper function infers the type T
from the mapped type of et
. Now you can use it like this:
const elementsTyped = asElementTypes({
square: { nodes: 4, symmetric: true },
triangle: { nodes: 3 },
line: { nodes: 2, notSymmetric: false /* error where you want it */}
});
结果 elementsTyped
的类型(一旦您修复错误)将推断出键 square
、triangle
和 line
,值为 ElementType
.
The type of the resulting elementsTyped
will (once you fix the error) have inferred keys square
, triangle
, and line
, with values ElementType
.
希望对你有用.祝你好运!
Hope that works for you. Good luck!
这篇关于如何让 Typescript 推断对象的键但定义其值的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!