如果我有一个类型,它看起来像一个数组:
type names = ['Mike', 'Jeff', 'Ben'];
我可以轻松定义的另一种类型在names
项目的值:
type UserName = names[number]
对于函数:
function hello(name: UserName) {
console.log(`Hello, ${name}!`)
}
我只能通过Mike
,Jeff
,Ben
运作hello
之一。如果我给其他的值,比如John
,它不能编译。
如果我没有什么类型names
,而是一个常量数组names
?
const names = ['Mike', 'Jeff', 'Ben'];
type UserName = ???;
function hello(name: UserName) {
console.log(`Hello, ${name}!`)
}
hello('Mike');
是否有可能定义这种类型UserName
?
在TypeScript 3.4, which should be released in March 2019将有可能告诉编译器来推断字符串文字的元组的类型为字符串文字的元组,而不是作为string[]
,通过使用as const
syntax。它应该是这样的:
const names = ['Mike', 'Jeff', 'Ben'] as const; // TS3.4 syntax
type Names = typeof names; // type Names = readonly ['Mike', 'Jeff', 'Ben']
type UserName = Names[number]; // 'Mike' | 'Jeff' | 'Ben'
在此之前(以打字稿3.0通过3.3),你可以通过使用一个辅助功能,这使编译器提示来推断一个更小的类型得到这样的效果:
type Narrowable = string | number | boolean | undefined | null | void | {};
const tuple = <T extends Narrowable[]>(...t: T)=> t;
const names = tuple('Mike', 'Jeff', 'Ben');
type Names = typeof names; // type Names = ['Mike', 'Jeff', 'Ben']
type UserName = Names[number]; // 'Mike' | 'Jeff' | 'Ben'
(请注意,在这两种情况下,你可以跳过中间Names
类型,只是定义type UserName = (typeof names)[number]
如果你喜欢)
好了,希望有所帮助。祝好运!
同样,一个最应该的时候:
正是在这个顺序。
很少是应该做相反的事。
如果你真的需要它,虽然,你可以做这样的:
const names = ['Mike', 'Jeff', 'Ben'] as ['Mike', 'Jeff', 'Ben'];
type UserName = typeof names;
因为你想有一个元组类型(['Mike', 'Jeff', 'Ben']
),但阵列从未推断为默认的元组,但只能作为阵列(在这种情况下string[]
)。但是我看不出太大的意义上面的事情做,再次我建议你做相反,惯用的事情:
type UserName = ['Mike', 'Jeff', 'Ben'];
// however the above type is absolutely static
// and I don't know if it can provide any benefit so maybe this is more correct:
type UserName = ('Mike' | 'Jeff' | 'Ben')[]
const names: UserName = ['Mike', 'Jeff', 'Ben'] // ok