我可以使用打字稿将对象键限制为枚举值吗?

Can I constrain an objects keys to an enums values using typescript?

本质上,我想要一种方法来确保选项参数具有作为特定枚举值的键:

//enum Mode { Foo, Bar };
interface Mode { Foo: number, Bar: number }

interface View { 
    text: string;
};

class FooView implements View {
    text = 'foo';
 }

class BarView implements View { 
    text = 'bar';
}

function initialize(options: { mode: {[P in keyof Mode]?: View} }) {
    let mode: View = options.mode.Foo;
}

initialize({ mode: { Bar: new FooView() } });

如果我使用 interface/class 而不是枚举,它会完美地工作,但这确实是一个枚举(概念上)...

this playground

键必须是字符串或数字。您可以这样做,但是您必须使用括号语法并将对象的键设置为数字:

enum Mode { Foo, Bar };

function initialize(options: { mode: {[key:number]: View} }) {
    let mode: View = options.mode[Mode.Foo];
}

initialize({ mode: { [Mode.Bar]: new FooView() } });

这个答案的想法来自Sohnee's

显然这里的警告是有人可以很容易地做类似

的事情
initialize({ mode: { [999]: new FooView() } });

不太理想。如果该值不是有效模式,您可以做的最好的事情是在 运行 时间抛出错误:

if (!Object.keys(options.mode).every((key) => key in Mode)) {
    throw new Error("Nice try");
}