2015-02-12 4 views
1

У меня есть тип объекта, который может быть расширен в JavaScriptExtensible Object В Машинопись Определение

var myObject = Library.LibraryType(); 

myObject.myExtension = MyExtension(); 

Пока расширение придерживается какой-то интерфейс, то LibraryType может сделать полезные вещи с ним.

Но как это выразить в файле определения машинописных текстов? Я не хочу, чтобы пользователи все время делали все до <any>.

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

export interface IExtension { 
} 
export interface IExtensibleLibraryType { 
    something: string; 
    otherthing: (args: number) => void; 

    [ keyOfExtension: string ]: IExtension; 
} 

В нем говорится, что все остальные члены не являются IExtension.

Я бы подумал, что компилятор только бы ввел в действие, что к членам словаря обращаются как к словарю mytype['keyOfExtension'], к которому можно получить доступ ко всем другим членам с помощью нотации .? Почему это не так?

Есть ли способ обойти это? Или Мне просто нужно сказать всем, чтобы они набрали any все время? Или заставляют пользователей расширять сами интерфейсы в своем собственном коде (лучший вариант, но я уверен, что люди с большей вероятностью будут делать первые)?

Мне бы очень хотелось, чтобы .d.ts мог полностью описать API библиотеки, как полезное дополнение к документам.

ответ

1

Машинопись в настоящее время имеет лучшую поддержку для классического OO, чем для подхода, который вы используете.

class LibraryType { 
    constructor() { 
     // equivalent of your Library.LibraryType() function 
    } 

} 

class MyExtendedVersion extends LibraryType { 
    extension: blah 
} 

К сожалению, для этого вам необходимо изменить способ работы вашей библиотеки. Вместо экспорта фабричной функции вам нужно экспортировать класс. И внутренне код вашего класса должен будет использовать this для доступа к своим собственным данным экземпляра.

При переносе моего собственного крупномасштабного проекта в TS я попробовал классическое преобразование для нескольких файлов и быстро сдался. Это был «переписывающий» опыт, что плохо, потому что мне нужно исправить ошибки в предыдущей версии и объединить их в версию TS. Гораздо проще перейти на TS, если все, что вам нужно сделать, это добавить несколько аннотаций типа здесь и там. Поэтому я использую интерфейсы, $.extend и литье (утверждения типа), чтобы избежать необходимости переписывать.

Существует request for a language feature here, который может помочь нам в будущем, но пока это не на дорожной карте.

0

В нем говорится, что все остальные члены не являются IExtension.

Компилятор помогает вам здесь. Если вы скажете, что что-либо доступное по строке должно быть типа IExtension, то ваши собственные члены (например, something) должны соответствовать, чтобы разрешить foo['something'].

Fix:

шаг extensions один уровень вниз:

interface IExtension { 
    foo:string; 
} 
interface IExtensibleLibraryType { 
    something: string; 
    extensions: {[ keyOfExtension: string ]: IExtension}; 
} 

function getLib():IExtensibleLibraryType{ 
    return { 
     something:'', 
     extensions: {} 
    }; 
} 


var test = getLib(); 
test.extensions['good'] = {foo:'test'}; 
test.extensions['bad'] = {foos:'test'}; // Error 
Смежные вопросы