Самоссылающийся индексированный тип

Я хотел бы определить интерфейс, который имеет некоторые известные члены, а неизвестные члены должны сопоставляться с тем же типом. Я хотел бы иметь возможность определить:

interface Foo {
    name?: string;
    [others: string]: Foo;
}

Это позволило бы мне определить:

var myFoo: Foo = {
    name: 'foo1'
    anotherfoo: {
        name: 'foo2'
        yetanotherfoo: {
            name: 'foo3'
        }
    }
}

Однако мой интерфейс не компилируется со следующим сообщением об ошибке:

Свойство «имя» типа «строка» не может быть присвоено типу строкового индекса «Foo»

Единственный способ, которым мне удалось это сделать, — определить тип индекса с любым типом:

[others: string]: any;

Это позволяет коду компилироваться, но, очевидно, теряет безопасность типов и интеллектуальность для элементов, расположенных ниже.

Я не хочу, чтобы мне предлагали изменить мою структуру данных — на самом деле это нужно для исправления определения машинописного текста для библиотеки сопоставления нокаута, которая больше не работает для TS1.6 из-за того, что не разрешены неопределенные члены.


person Richard    schedule 26.10.2015    source источник


Ответы (1)


interface Foo {
    name?: string;
    [others: string]: Foo;
}

Объявление самопротиворечиво: в нем говорится, что каждое объявленное свойство этого типа является Foo, а name является string.

Чтобы это исправить, укажите, что все объявленные свойства имеют значение либо string, либо Foo:

interface Foo {
    name?: string;
    [others: string]: Foo|string;
}
person Ryan Cavanaugh    schedule 26.10.2015
comment
Спасибо - это не самое изящное решение (фактический класс, над которым я работаю, имеет 5 или 6 типов, включая делегатов), но это лучше, чем использование любого! - person Richard; 27.10.2015