Расширяемый объект в определении машинописного текста

У меня есть тип объекта, который можно расширить в javascript

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 библиотеки как полезное дополнение к документам.


person tigerswithguitars    schedule 12.02.2015    source источник


Ответы (2)


В настоящее время TypeScript лучше поддерживает классический объектно-ориентированный подход, чем тот подход, который вы используете.

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

}

class MyExtendedVersion extends LibraryType {
    extension: blah
}

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

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

Здесь есть запрос на языковую функцию, которая может помочь нам в будущем. , но пока этого нет в дорожной карте.

person Daniel Earwicker    schedule 22.03.2015

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

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

Исправить:

переместиться на 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 
person basarat    schedule 12.02.2015