2017-02-10 2 views
0

По существу, я хочу способ гарантировать, что опции аргумент имеет ключи, которые являются значением конкретного перечисления:Могу ли я ограничить ключи объектов значениями enums с помощью машинописного текста?

//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() } }); 

Он отлично работает, если я использую интерфейс/класс вместо перечисления, но это действительно перечисление (концептуально) ...

См this playground

ответ

0

Ключи должны быть либо строки или числа. Вы можете отчасти сделать это, но вы должны использовать синтаксис кронштейн и установить ключ вашего объекта в виде числа:

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 answer to a similar question.

Очевидно предостережение в том, что кто-то может так же легко сделать что-то вроде

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

Менее оптимальным. Лучшее, что вы могли бы сделать, - это выбросить ошибку во время выполнения, если значение недействительно.

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

Я думал об этих строках ... Определенно, без оптимального. Спасибо за информацию! – Lucas

Смежные вопросы