简体   繁体   English

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

[英]How to build a type from enum values in TypeScript?

Given the following:鉴于以下情况:

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

I'd like to make an interface like this one, but instead of defining keys by hand, build it out of enum's values.我想制作一个像这样的界面,但不是手动定义键,而是根据枚举的值构建它。

interface Foo {
  foo: string
  bar: string
}

Is something like this possible with TypeScript?使用 TypeScript 可以实现这样的事情吗?

Thanks!谢谢!

Yes, you can use enum values as keys.是的,您可以使用枚举值作为键。 And you can use a mapped type like the standard library's Record<K, V> to prevent repetition:您可以使用标准库的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 {};

And you can verify that it works:您可以验证它是否有效:

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

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

foo.baz; // error

Does that work for you?那对你有用吗? Good luck!祝你好运!

[@hackape 's solution][1] is great, but I found minimal duplication extending his solution as below: [@hackape 的解决方案][1] 很棒,但我发现扩展他的解决方案的重复最少,如下所示:

 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 implementation is well explained [here][2] ReverseMap 实现在 [这里][2] 中得到了很好的解释

[1]: https://stackoverflow.com/a/60768453/5519365 [2]: https://stackoverflow.com/a/55209457/5519365 [1]: https ://stackoverflow.com/a/60768453/5519365 [2]: https ://stackoverflow.com/a/55209457/5519365

Update: I found a much simpler solution for ReverseMap更新:我为 ReverseMap 找到了一个更简单的解决方案

const Obj = {
 FOO: 'foo',
 BAR: 'bar',
} as const;

type ReverseMap<T> = T[keyof T];

export type Values = ReverseMap<typeof Obj>; // 'foo' | 'bar';

Does this answer your question?这回答了你的问题了吗?

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

yes?是的?

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM