Typescript: добавить метод в класс из другого модуля/заполнить пространство имен из разных модулей

История

Я создаю модульную библиотеку для математических операций. Я также хочу разделить библиотеку на несколько модулей: core, relational, vectors и так далее. Модули можно использовать сами по себе (но все зависит от модуля core)

  1. Я знаю, что нельзя использовать частичные классы Как мне разделить класс TypeScript на несколько файлов? / https://github.com/Microsoft/TypeScript/issues/563

Проблема :

Модуль core определяет класс Set, представляющий собой математический набор. Он определяет такие операции, как Set#add, Set#remove.

Однако необязательный модуль relational добавляет Set#productoperator в Setclass.

Другие модули также могут добавлять другие операции в класс Set. Я хочу сохранить возможность добавления функциональности, когда сочту нужным.

Вопрос

  1. Как с помощью typescript добавить метод в класс, который находится в другом модуле?

  2. Как я могу организовать типизацию так, чтобы пользователь моей библиотеки видел Set#product в своем автозавершении кода только если он установил модуль relational? В противном случае он видит только операции #add и #remove?

Я разрабатываю эту библиотеку для node.js, но также использую browserify, чтобы связать ее для использования в браузере.

// core/set.ts 

export class Set {
  add(element){}
  remove(element){}
}


// relational/set.ts

import {Set} from './../core/set.ts';

Set.prototype.product = function(){} // ?


// app/index.js

import {core} from 'mylib';

var set = new Set();
set.add();
set.remove();
// set.product() is not available


// app/index2.js

import {core} from 'mylib';
import {relational} from 'mylib';

var set = new Set();
set.add();
set.remove();
set.product() //is available

Бонусный вопрос

Все эти модули доступны через общее пространство имен, назовем его MyLibrary. Модуль core добавляет MyLibrary.Core, а модуль relational добавляет некоторые объекты в MyLibrary.Core, а также добавляет MyLibrary.Relational.

Допустим, я публикую другой модуль, который используется только как фасад для других модулей. Назовем этот модуль my-library.

Если пользователь устанавливает модули my-library, core и relational с помощью npm.

npm install my-library && npm install core and nom-install relational

В клиентском приложении хотелось бы, чтобы пользователю библиотеки оставалось только написать

var lib = require('my-library');

Затем my-library автоматически проверит все установленные модули MyLibrary, потребует их, заполнит пространство имен MyLibrary и вернет его.

Как я сообщаю модулю my-library при первом доступе к нему как в узле, так и в браузере, чтобы

  1. Проверьте наличие любого доступного модуля MyLibrary (среды браузера и узла)
  2. Запустите метод для каждого модуля (чтобы установить их в пространство имен)
  3. Верните это красивое фруктовое пространство имен

person Ludovic C    schedule 24.12.2015    source источник
comment
Почему бы вам не использовать традиционное наследование классов?   -  person FlorianTopf    schedule 24.12.2015
comment
Потому что несколько модулей могут добавлять функциональность к одному и тому же классу.   -  person Ludovic C    schedule 24.12.2015
comment
Это как частичные классы С#   -  person Ludovic C    schedule 24.12.2015


Ответы (1)


Если вы просто пишете файлы объявлений, вы можете вместо этого использовать интерфейсы и делать что-то вроде того, что moment-timezone делает.

момент.д.ц

declare module moment {
    interface Moment {
        // ...
    }

    interface MomentStatic {
        // ...
    }
}
declare module 'moment' {
    var _tmp: moment.MomentStatic;
    export = _tmp;
}

момент-часовой пояс.d.ts

Просто повторно объявите те же интерфейсы с дополнительными функциями.

declare module moment {
    interface Moment {
        tz(): void;
    }

    interface MomentStatic {
        tz(): void;
    }
}
declare module 'moment-timezone' {
    var _tmp: moment.MomentStatic;
    export = _tmp;
}

Оба пакета теперь идентичны, и moment автоматически получает новые методы.

person Louay Alakkad    schedule 25.12.2015
comment
Всем привет. Проблема в том, что я пишу все это в машинописном тексте, а не только в файлах объявлений... - person Ludovic C; 26.12.2015
comment
В этом случае я считаю, что вам придется писать файлы объявлений вручную или использовать инструмент для их создания. В обоих случаях вы можете полагаться только на интерфейсы. Другого варианта я не знаю, к сожалению. - person Louay Alakkad; 26.12.2015