Typescript:根据枚举成员的数量获取一个固定长度的元组

Posted

技术标签:

【中文标题】Typescript:根据枚举成员的数量获取一个固定长度的元组【英文标题】:Typescript: Get a tuple with the fixed length according to the number of enum members 【发布时间】:2020-09-19 08:32:21 【问题描述】:

假设我有一个枚举

enum Chest 
  ID,
  NAME,
  CAPACITY,
  OPEN_WIN_POINTS,

我想创建一个长度与枚举中值的数量相同的元组。所以对于上面的例子,我想要长度为 4 的字符串元组:

type ChestStringTuple = EnumTuple<string, Chest>

const correctTuple: ChestStringTuple = ['foo', 'bar', 'baz', 'goo']
const incorrectTuple1: ChestStringTuple = ['foo', 'bar', 'baz']  // The number of tuple members differs from 4
const incorrectTuple2: ChestStringTuple = ['foo', 'bar', 'baz', false]  // The tuple has non-string members

有没有办法获取枚举成员的数量并将其用作元组长度?

【问题讨论】:

相关***.com/questions/52489261/… @AlekseyL。这是一个很好的,谢谢!如果我只能以某种方式获得枚举长度。 不要认为这是可能的。尝试描述什么是真正的用例,也许有人可以提供帮助 【参考方案1】:

结合 SO 上提出的各种问题的解决方案,我设法创建了一个应该正是您正在寻找的解决方案!

首先,let's grab a type that can build us a tuple!

type BuildTuple<Current extends [...T[]], T, Count extends number> =
  Current["length"] extends Count
    ? Current
    : BuildTuple<[T, ...Current], T, Count>

type Tuple<T, Count extends number> = BuildTuple<[], T, Count>

Then we'll hop on over to this SO question, which has some really useful union helper functions!

type UnionToIntersection<U> =(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
type UnionToOvlds<U> = UnionToIntersection<U extends any ? (f: U) => void : never>;
type PopUnion<U> = UnionToOvlds<U> extends ((a: infer A) => void) ? A : never;

然后我们将重写该 SO 答案的主要方法,因为我们的目标不是将联合转换为元组(我不建议这样做 - read this for an explanation as to why)

type UnionCount<U, L extends any[] = []> = 
  0: PopUnion<U> extends infer SELF ? UnionCount<Exclude<U, SELF>, [any, ...L]> : never;
  1: L['length'];
[[U] extends [never] ? 1 : 0];

从那里开始,剩下的就相当简单了。我们将制作几个别名类型,以便于阅读

type InterfaceLength<T> = UnionCount<keyof T>;
type EnumLength<T> = UnionCount<T>;

如果我们将所有这些组合在一起,我们就可以创建我们的final枚举

type InterfaceTuple<T, L> = Tuple<T, InterfaceLength<L>>;
type EnumTuple<T, L> = Tuple<T, EnumLength<L>>;

您的代码:

enum Chest 
  ID,
  NAME,
  CAPACITY,
  OPEN_WIN_POINTS,


type ChestStringTuple = EnumTuple<string, Chest>

const correctTuple: ChestStringTuple = ['foo', 'bar', 'baz', 'goo']    // Valid
const incorrectTuple1: ChestStringTuple = ['foo', 'bar', 'baz']        // Not valid
const incorrectTuple2: ChestStringTuple = ['foo', 'bar', 'baz', false] // Not valid

Playground

使用风险自负。

【讨论】:

我想知道是否有更简洁的方法来获取联合中的元素数量。 . .

以上是关于Typescript:根据枚举成员的数量获取一个固定长度的元组的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript入门-枚举类型推论

用于将字符串枚举成员转换为枚举的Typescript函数

Typescript学习笔记枚举

是否可以在 Typescript 中定义没有显式类型的枚举?

LayaBox---TypeScript---枚举

Typescript 中的枚举类型是啥?