给出以下内容:
enum FooKeys {
FOO = 'foo',
BAR = 'bar',
}
我想创建一个像这样的接口,但不要手动定义键,而应使用枚举的值来构建它。
interface Foo {
foo: string
bar: string
}
使用TypeScript可以实现这种效果吗?
谢谢!
答案 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