我有一个字符串联合类型,如下所示:
type Suit = 'hearts' | 'diamonds' | 'spades' | 'clubs';
我想要一种类型安全的方法来获取可以在此字符串联合中使用的所有可能值 . 但由于接口主要是设计时构造,我能做的最好的就是:
export const ALL_SUITS = getAllStringUnionValues<Suit>({
hearts: 0,
diamonds: 0,
spades: 0,
clubs: 0
});
export function getAllStringUnionValues<TStringUnion extends string>(valuesAsKeys: { [K in TStringUnion]: 0 }): TStringUnion[] {
const result = Object.getOwnPropertyNames(valuesAsKeys);
return result as any;
}
这没关系,该函数确保我总是传递一个对象,其中每个键是字符串union中的一个元素,并且每个元素都包含在内,并返回所有元素的字符串数组 . 因此,如果字符串union更改,则在编译时对此函数的调用将发生错误(如果还未更新) .
但 the problem is 常量 ALL_SUITS
的类型签名是 ('hearts' | 'diamonds' | 'spades' | 'clubs')[]
. 换句话说,TypeScript认为它是一个包含没有或多个这些值的数组,可能带有重复项,而不是只包含所有值的数组,例如 ['hearts', 'diamonds', 'spades', 'clubs']
.
我真正喜欢的是我的通用 getAllStringUnionValues
函数指定它返回 ['hearts', 'diamonds', 'spades', 'clubs']
的方法 .
如何尽可能DRY实现这个 generically ?
1 回答
2018年7月更新
看起来,从TypeScript 3.0开始,TypeScript可以automatically infer tuple types . 一旦发布,您需要的
tuple()
功能可以简洁地写为:然后你可以像这样使用它:
2017年8月更新
自从我发布这个答案后,如果你愿意为你的库添加一个函数,我找到了一种推断元组类型的方法 . 查看tuple.ts中的函数
tuple()
.使用它,您可以编写以下内容而不必重复:
你怎么看?
原始答案
获得所需内容的最简单方法是明确指定元组类型并从中派生联合,而不是试图强制TypeScript执行相反的操作,即doesn't know how to do . 例如:
请注意,您仍然会将文字写出两次,一次作为
SuitTuple
中的类型,一次作为ALL_SUITS
中的值;你没有很好的方法可以避免以这种方式重复自己,因为当前无法将TypeScript告知infer tuples,它将从元组类型生成运行时数组never .这里的优点是您不需要在运行时对虚拟对象进行密钥枚举 . 如果你仍然需要它们,你当然可以用西装作为键来构建类型:
希望有所帮助 .