Как вы пишете модуль node с помощью typescript?

Итак, общий ответ на другой вопрос (как вы импортируете модуль с помощью typescript):

1) Создайте файл определения blah.d.ts.

2) Использование:

/// <reference path="./defs/foo/foo.d.ts"/>
import foo = require("foo");

Критически вам нужны файлы foo.d.ts и foo.js где-то в вашем node_modules для загрузки; и NAME foo должно точно совпадать для обоих. Теперь...

Вопрос, на который я хотел бы ответить, - это как написать модуль typescript, который вы можете импортировать таким образом?

Скажем, у меня есть такой модуль:

- xq/
- xq/defs/Q.d.ts
- xq/index.ts
- xq/base.ts
- xq/thing.ts

Я хочу экспортировать модуль "xq" с классами "Base" из base.ts и "Thing" из thing.ts.

Если это был модуль node в javascript, мой index.ts выглядел бы примерно так:

var base = require('./base');
var thing = require('./thing');
module.exports = {
  Base: base.Base,
  Thing: thing.Thing
};

Попробуйте использовать похожий файл typescript:

import base = require('./base');
export module xq {
    export var base = base.Base;
}

Вызовите его:

tsc base.ts index.ts things.ts ... --sourcemap --declaration --target ES3 
                                   --module commonjs --outDir dist/xq

Что происходит? Ну, мы получаем наш base.d.ts:

export declare class Base<T> {
  ...
}

и невероятно неудобный index.d.ts:

export declare module xq {
    var Base: any; // No type hinting! Great. :(
}

и полностью недействительный javascript, который не вызывает импорт модуля:

(function (xq) {
    xq.base = xq.base.Base;
})(exports.xq || (exports.xq = {}));
var xq = exports.xq;

Я пробовал кучу вариаций по теме, и единственное, что я могу получить, это:

declare var require;
var base = require('./base');
export module xq {
    export var base = base.Base;
}

... но это явно полностью уничтожает проверку типов.

Итак.

Typescript отлично, но этот модуль полностью отстой.

1) Возможно ли это сделать со встроенным генератором определений (я сомневаюсь)

2) Как вы это делаете вручную? Я видел заявления импорта в файлах .d.ts, которые, как я полагаю, означает, что кто-то выяснил, как это сделать; как они работают? Как вы делаете typescript для модуля, в котором есть объявление с импортом?

(например, я подозреваю, что правильный способ сделать объявление модуля:

/// <reference path="base.d.ts" />
declare module "xq" {
  import base = require('./base'); 
  module xq {
    // Some how export the symbol base.Base as Base here
  }
  export = xq;
}

... но я понятия не имею, что будет с этим typescript).

Ответ 1

Для JavaScript:

var base = require('./base');
var thing = require('./thing');
module.exports = {
  Base: base.Base,
  Thing: thing.Thing
};

TypeScript:

import base = require('./base');
import thing = require('./thing');
var toExport = {
  Base: base.Base,
  Thing: thing.Thing
};
export = toExport;

Или даже этот typescript:

import base = require('./base');
import thing = require('./thing');
export var Base = base.Base;
export var Thing = thing.Thin;

Ответ 2

Typescript действительно улучшился, так как этот вопрос был задан. В последних версиях Typescript язык стал намного более строгим надмножеством Javascript.

Правильный способ импорта/экспорта модулей - это новый синтаксис модуля ES6:

myLib.ts

export function myFunc() {
  return 'test'
}

package.json

{
  "name": "myLib",
  "main": "myLib.js",
  "typings": "myLib.d.ts"
}

Зависимые могут затем импортировать ваш модуль с использованием нового синтаксиса ES6:

dependent.ts

import { myFunc } from 'myLib'

console.log(myFunc())
// => 'test'

Для полного примера модуля node, написанного в Typescript, проверьте этот шаблон:

https://github.com/bitjson/typescript-starter/