打字稿从元组/数组值派生联合类型
说我有清单const list = ['a', 'b', 'c']
是否可以从 'a' 的值联合类型派生?'b' |'c'
?
我想要这个是因为我想定义只允许来自静态数组的值的类型,并且还需要在运行时枚举这些值,所以我使用数组.
I want this because I want to define type which allows only values from static array, and also need to enumerate these values at runtime, so I use array.
示例如何使用索引对象实现:
Example how it can be implemented with an indexed object:
const indexed = {a: null, b: null, c: null}
const list = Object.keys(index)
type NeededUnionType = keyof typeof indexed
我想知道是否可以在不使用索引地图的情况下做到这一点.
I wonder if it is possible to do it without using an indexed map.
2019 年 2 月更新
在 TypeScript 3.4 中,应于 2019 年 3 月发布 可以告诉编译器将文字元组的类型推断为文字元组,而不是例如 string[]
,通过使用as const
语法.这种类型的断言会导致编译器为值推断出可能的最窄类型,包括将所有内容设为 readonly
.它应该是这样的:
UPDATE Feb 2019
In TypeScript 3.4, which should be released in March 2019 it will be possible to tell the compiler to infer the type of a tuple of literals as a tuple of literals, instead of as, say, string[]
, by using the as const
syntax. This type of assertion causes the compiler to infer the narrowest type possible for a value, including making everything readonly
. It should look like this:
const list = ['a', 'b', 'c'] as const; // TS3.4 syntax
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c';
这将消除对任何类型的辅助函数的需求.再次祝大家好运!
This will obviate the need for a helper function of any kind. Good luck again to all!
看起来,从 TypeScript 3.0 开始,TypeScript 可以自动推断元组类型.一旦被释放,你需要的tuple()
函数可以简洁地写成:
It looks like, starting with TypeScript 3.0, it will be possible for TypeScript to automatically infer tuple types. Once is released, the tuple()
function you need can be succinctly written as:
export type Lit = string | number | boolean | undefined | null | void | {};
export const tuple = <T extends Lit[]>(...args: T) => args;
然后你可以像这样使用它:
And then you can use it like this:
const list = tuple('a','b','c'); // type is ['a','b','c']
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
希望对人们有用!
自从我发布这个答案后,如果您愿意向库中添加函数,我找到了一种推断元组类型的方法.查看 tuple.ts 中的函数 tuple()
.使用它,您可以编写以下内容而不再重复自己:
Since I posted this answer, I found a way to infer tuple types if you're willing to add a function to your library. Check out the function tuple()
in tuple.ts. Using it, you are able to write the following and not repeat yourself:
const list = tuple('a','b','c'); // type is ['a','b','c']
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
祝你好运!
一个问题是文字 ['a','b','c']
会被推断为类型 string[]
,所以类型系统会忘记关于具体数值.您可以强制类型系统将每个值作为文字字符串记住:
One problem is the literal ['a','b','c']
will be inferred as type string[]
, so the type system will forget about the specific values. You can force the type system to remember each value as a literal string:
const list = ['a' as 'a','b' as 'b','c' as 'c']; // infers as ('a'|'b'|'c')[]
或者,也许更好,将列表解释为元组类型:
Or, maybe better, interpret the list as a tuple type:
const list: ['a','b','c'] = ['a','b','c']; // tuple
这是烦人的重复,但至少它不会在运行时引入无关对象.
This is annoying repetition, but at least it doesn't introduce an extraneous object at runtime.
现在你可以像这样得到你的工会:
Now you can get your union like this:
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'.
希望有所帮助.