如何从TypeScript中的枚举值构建类型?

时间:2019-03-13 12:41:14

标签: typescript types typescript-generics

给出以下内容:

enum FooKeys {
  FOO = 'foo',
  BAR = 'bar',
}

我想创建一个像这样的接口,但不要手动定义键,而应使用枚举的值来构建它。

interface Foo {
  foo: string
  bar: string
}

使用TypeScript可以实现这种效果吗?

谢谢!

4 个答案:

答案 0 :(得分:2)

是的,您可以将枚举值用作键。而且您可以像标准库的mapped type一样使用Record<K, V>来防止重复:

enum FooKeys {
  FOO = 'foo',
  BAR = 'bar',
}

// probably all you need, but it's a type alias
type FooType = Record<FooKeys, string>;

// if you need an interface instead you can do this
interface FooInterface extends FooType {};

您可以验证它是否有效:

declare const foo: FooInterface;
foo.foo; // okay
foo[FooKeys.FOO]; // okay

foo.bar; // okay
foo[FooKeys.BAR]; // okay

foo.baz; // error

这对您有用吗?祝好运!

答案 1 :(得分:0)

是吗?

enum FooKeys {
  FOO = 'foo',
  BAR = 'bar',
}

interface Foo {
  foo: string
  bar: string
}

class Test implements Foo {
    public foo: string = FooKeys.FOO;
    public bar: string = FooKeys.BAR;
}

答案 2 :(得分:0)

@hackape 's solution很好,但是我发现重复最少,扩展了他的解决方案,如下所示:

type ReverseMap<T extends Record<keyof T, any>> = {
  [V in T[keyof T]]: {
    [K in keyof T]: T[K] extends V ? K : never;
  }[keyof T];
}

const Map = {
  'FOO': "foo" as "foo",
  'BAR': "bar" as "bar",
}

const reverseMap: ReverseMap<typeof Map> = Object.entries(Map).reduce((rMap, [k, v]) => {
  rMap[v] = k;
  return rMap;
}, {} as any);

export type Values = keyof typeof reverseMap; // 'foo' | 'bar';

ReverseMap的实现已得到很好的解释here

答案 3 :(得分:0)

这是否回答了您的问题?

enum FOO_BAR {
    F = "foo",
    B = "bar",
}

type FooType = Record<FOO_BAR, string>;

const obj: FooType = {
    // you can use enum values, better for refactoring
    [FOO_BAR.F]: "action foo",
    [FOO_BAR.B]: "action bar",

    // or use enum values
    // foo: "action foo",
    // bar: "action bar",
};

obj[FOO_BAR.F]; // -> "action foo"
obj["foo"];     // -> "action foo"

// If you want partial keys
type FooTypePartial = Partial<FooType>;

const objPartial: FooTypePartial = {
    [FOO_BAR.F]: "action foo",
};

objPartial["foo"]; // -> "action foo", may be undefined