2019年2月更新
在将于2019年3月发布的TypeScript 3.4中,通过使用as const语法,可以告诉编译器将文字元组的类型推断为文字元组,而不是作为string[]。这种类型的断言导致编译器推断值的最窄类型,包括使所有内容都为只读。它应该是这样的:
const list = ['a', 'b', 'c'] as const; // TS3.4 syntax
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c';
这将消除对任何类型的帮助函数的需要。再次祝大家好运!
2018年7月更新
看起来,从TypeScript 3.0开始,TypeScript将有可能自动推断元组类型。一旦被释放,你需要的tuple()函数可以简单地写成:
export type Lit = string | number | boolean | undefined | null | void | {};
export const tuple = <T extends Lit[]>(...args: T) => args;
然后你可以这样使用它:
const list = tuple('a','b','c'); // type is ['a','b','c']
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
希望这对人们有用!
2017年12月更新
自从我发布了这个答案,我发现了一种推断元组类型的方法,如果你愿意向你的库中添加一个函数。在tuple.ts中检出函数tuple()。使用它,你可以写出以下内容,而不必重复:
const list = tuple('a','b','c'); // type is ['a','b','c']
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
好运!
2017年7月
一个问题是字面量['a','b','c']将被推断为类型字符串[],因此类型系统将忘记具体的值。你可以强制类型系统将每个值都记为字面值字符串:
const list = ['a' as 'a','b' as 'b','c' as 'c']; // infers as ('a'|'b'|'c')[]
或者,更好的是,将列表解释为元组类型:
const list: ['a','b','c'] = ['a','b','c']; // tuple
这是令人讨厌的重复,但至少它不会在运行时引入无关的对象。
现在你可以像这样得到你的工会:
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'.