在我的定义文件中有这个对象
export const properties = {
name: '',
level: ['a', 'b', 'c'],
uri: '',
active: true
}
(注意:它不是一个接口,它实际上是一个真正的对象,我需要一个对象的原因是因为我需要它作为运行时的引用)
现在我试着从这个对象中创建一个类型,这就是我需要的
export type Properties = {
name: string;
level: 'a'|'b'|'c';
uri: string;
active: boolean
}
我试过使用
export type Properties = typeof properties
但是level
被翻译为string[]
,这是正常的,但是我如何使用TypeScript将['a', 'b', 'c']
映射到'a'|'b'|'c'
?如果可能的话我怎么在一个类型到另一个类型的映射中做到这一点呢?
如果您完全按照上面所做的定义properties
,那么它将不起作用。当您开始编写type Properties =
时,编译器已经将level
属性扩展为string[]
,并且忘记了其元素的字符串文字类型,如您所见。
"a" | "b" | "c"
从properties
中取出,您将需要更改properties
的定义。最简单的方法是使用const
断言给编译器一个提示,表明您想要它可以推断的最窄类型。例如:const properties = {
name: '',
level: ['a', 'b', 'c'] as const,
uri: '',
active: true
}
我们将level
断言为const
,现在typeof properties
看起来是这样的:
/* const properties: {
name: string;
level: readonly ["a", "b", "c"];
uri: string;
active: boolean;
} */
那么,我们如何将其转换为Properties
呢?假设问题是"如何在一个类型到另一个类型的映射中做到这一点?"这意味着您希望将每个类似数组的东西都转换为其元素类型,并且假设您只需要做这一层(而不是递归地),那么您可以定义这个类型函数:
type Transform<T> = { [K in keyof T]:
T[K] extends readonly any[] ? T[K][number] : T[K]
}
这是一个映射类型,我们接受输入类型T
,对于每个属性键K
,我们索引它以获得它的属性类型(T[K]
)。如果该属性类型不是数组(readonly any[]
实际上比any[]
更通用),则不处理它。如果是数组,那么我们通过使用number
索引来获取它的元素类型(如果您有一个数组arr
和一个数字n
,那么arr[n]
将是一个元素)。
对于typeof properties
,结果:
type Properties = Transform<typeof properties>
/* type Properties = {
name: string;
level: "a" | "b" | "c";
uri: string;
active: boolean;
} */
。
Playground链接到代码