typescript 如何从另一个枚举声明子集枚举

daolsyd0  于 2023-05-19  发布在  TypeScript
关注(0)|答案(2)|浏览(127)

然后是代码:

enum all {
  a = 'a',
  b = 'b',
  c = 'c',
}

// what I want enum
enum wanted {
  c = 'c',
}

我知道有一些解决办法比如

type wanted = Exclude<all, all.a | all.b> // type wanted = all.c

但是类型不同于枚举,因为它不是可迭代的!

vlju58qv

vlju58qv1#

枚举只是运行时的一个对象。例如,你的enum all被转换为:

var all;
(function (all) {
    all["a"] = "a";
    all["b"] = "b";
    all["c"] = "c";
})(all || (all = {}));

// Essentially equivalent to
const all = {a: 'a', b: 'b', c: 'c'}

因此,您可以像使用任何普通JavaScript对象一样使用allpick/omit certain properties有很多不同的方法:

// ES2015 Destructuring
const {a, b, ...wanted} = all

// ES2019 Object.fromEntries
const wanted = Object.fromEntries(
  Object.entries(all)
    .filter(([key]) =>
      key === 'c'
      // or if you wanted to exclude instead
      // !['a', 'b'].includes(key)
    )
) as {c: 'c'}

如果你想让最后一个例子更加类型安全,你可以使用这个助手:

const pick = <T extends Record<string, unknown>, K extends keyof T>(
  obj: T,
  keys: readonly K[]
): Pick<T, K> =>
  Object.fromEntries(
    Object.entries(obj).filter(([key]) =>
      (keys as readonly string[]).includes(key)
    )
  ) as Pick<T, K>

const wanted = pick(all, ['c'])

或者可以这样省略属性:

const omit = <T extends Record<string, unknown>, K extends keyof T>(
  obj: T,
  keys: readonly K[]
): Omit<T, K> =>
  Object.fromEntries(
    Object.entries(obj).filter(([key]) =>
      !(keys as readonly string[]).includes(key)
    )
  ) as Omit<T, K>

const wanted = omit(all, ['a', 'b'])

在TypeScript中,类型可以与值具有相同的名称,因此如果您希望wanted也是一种类型(就像您写出枚举一样),则可以使用ExcludePick定义类型wanted(就像您的示例中一样)。
Playground链接

bkhjykvo

bkhjykvo2#

我实际上找到了一个合并enum的解决方案

enum Mammals {
  Humans = 'Humans',
  Bats = 'Bats',
  Dolphins = 'Dolphins'
}

enum Reptiles {
  Snakes = 'Snakes',
  Alligators = 'Alligators',
  Lizards = 'Lizards'
}

export const Animals = { ...Mammals, ...Reptiles };
export type Animals = typeof Animals;

所以你可以导入Animals作为枚举。

相关问题