当前答案
在 TypeScript 3.4 及更高版本中,您可以使用const断言 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions告诉编译器保留特定的文字类型 https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types of any 文字值 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#literals在一个表达式中。
const list = ['a', 'b', 'c'] as const; // const assertion
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c';
Playground 代码链接 https://www.typescriptlang.org/play?#code/MYewdgzgLgBANgS2jAvDA2gcgIaYDQyYBG+hwmAujNhDKJFANwwD0LMAKgMoDMAdABYYEAJ5go2AB4AoKCIAOAUxgA5RYoAmmgKpgE4DguVo5SkADN4SKOjABXALZFFAJwrM2hXAB9imX+SMQA
2019 年 2 月更新
In TypeScript 3.4,预计于 2019 年 3 月发布 https://github.com/Microsoft/TypeScript/wiki/Roadmap#34-march-2019可以告诉编译器推断文字元组的类型作为文字元组,而不是说,string[]
,通过使用as const syntax https://github.com/Microsoft/TypeScript/pull/29510。这种类型的断言使编译器推断出值可能的最窄类型,包括使所有内容readonly
。它应该看起来像这样:
const list = ['a', 'b', 'c'] as const; // TS3.4 syntax
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c';
这将消除对任何类型的辅助函数的需要。再次祝大家好运!
2018 年 7 月更新
看起来,从 TypeScript 3.0 开始,TypeScript 将有可能自动推断元组类型 https://github.com/Microsoft/TypeScript/pull/24897。一旦被释放,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()
in tuple.ts https://gist.github.com/jcalz/381562d282ebaa9b41217d1b31e2c211。使用它,您可以编写以下内容而不必重复自己:
const list = tuple('a','b','c'); // type is ['a','b','c']
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
祝你好运!
原版 2017 年 7 月
一个问题是字面意思['a','b','c']
将被推断为类型string[]
,因此类型系统会忘记具体的值。您可以强制类型系统将每个值记住为文字字符串:
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'.