如何在没有枚举开销的情况下获取字符串文字类型的数组值

时间:2017-09-12 12:16:55

标签: typescript

在我的项目中,我需要一些字符串文字类型和允许值的数组,用于类型守护等variuos任务。

这就是我们所拥有的:

type Animal = 'cat' | 'dog' | 'rabbit' | 'snake'
const animals: Animal[] = ['cat', 'dog', 'rabbit', 'snake']

它有效,但需要在源代码中多次列出键。

另一种方法是使用Get array of string literal type values中建议的枚举,但它会在运行时产生开销,因为枚举的编译代码比数组大。

我找到了另一种没有运行时开销的方法,但是我不确定它是否会在将来运行,因为它可能是一个错误。

const notWidened = <T extends string>(val: T[]) => val

const animals = notWidened(['cat', 'dog', 'rabbit', 'snake'])
type Animal = typeof animals[0]

所以问题是如果使用这个片段是安全的,或者它将来会破坏。有没有更好的方法来获得文字字符串类型和数组而不重复。

2 个答案:

答案 0 :(得分:2)

目前我找不到一个很好的文档,但你的notWidened()函数运行正常并且不是bug。如果将类型参数约束为string或子类型为string,TypeScript将推断泛型类型变量的字符串文字。因此,<T extends keyof U><T extends string><T extends 'a'|'b'>等将推断T的字符串文字。 (如果同样约束number,也可以推断booleanT文字。

所以,就我所见,你的代码很好;我可能做的唯一不同的是

type Animal = (typeof animals)[number]

而不是

type Animal = typeof animals[0]

因为0的{​​{1}}元素实际上是animals,即使你告诉TypeScript它是'cat'。不过,你很好。

如上所述,如果您希望TypeScript将'cat'|'dog'|...视为animals类型为animals[0]的元组,而'cat'的类型为{{1}等等,您可以使用tuple.ts 中的函数animals[1] 2018年7月更新>,从TypeScript 3.0开始,编译器将能够infer tuple types automatically,所以功能可以更简洁):

'dog'

这对你来说可能会派上用场。

TL; DR:您的代码没问题。

希望有所帮助;祝你好运!

答案 1 :(得分:1)

也许你可以使用 const 枚举字符串,这没有运行时开销。它将值编译为代码(Playground):

const enum Animals {
  Cat = 'cat',
  Dog = 'dog',
  Rabbit = 'rabbit',
  Snake = 'snake'
}

alert(Animals.Cat)

// Generated JavaScript code: 
// alert("cat" /* Cat */);