Допустим, у вас есть следующий модуль TypeScript:
function foo () {
return 123;
}
//TODO: Export code here
Я хочу экспортировать его таким образом, чтобы его можно было импортировать из TypeScript следующими способами:
import foo from 'foo';
import * as foo from 'foo';
и таким образом из узла:
const foo = require ( 'foo' );
Требования:
allowSyntheticDefaultImportsПока что я придумал следующие «решения», но они либо недостаточно хорошо сохраняют определения типов, либо слишком подробны:
export = foo['default'] = foo as typeof foo & { default: typeof foo };
export = foo['default'] = foo;
Есть ли способ лучше?
Вы должны использовать esModuleInterop, если хотите, чтобы и import foo, и import * as foo давали вам одно и то же. Это не поведение модуля, совместимого со спецификацией ES.
@unional Я экспортирую его как пакет commonjs. @Aaron, если я установил esModuleInterop в файле tsconfig.json моего пакета TS, я не вижу изменений в скомпилированном коде, должен ли я экспортировать модуль определенным образом?
В таком случае да, вам не нужен веб-пакет





Насколько мне известно, экспорт и импорт еще не поддерживаются в NodeJS. Проверьте эту статью: node-js-syntaxerror-неожиданный-импорт-токен
И, насколько мне известно, единственный способ использовать синтаксис типов TypeScript - только в файле .ts, поэтому можно скомпилировать необходимые файлы .ts в .js с помощью Babel.
Да, я уже этим занимаюсь. Но я не могу найти фактического экспорта модуля из TS, чтобы он генерировал правильные определения типов.
Поскольку вы публикуете как пакет commonjs, вам не нужен rollup / webpack.
Все, что вам нужно, это перенести ваш код в es5 в commonjs с помощью компилятора TypeScript.
Ваш tsconfig.json должен выглядеть так:
// tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"target": "es5",
"outDir": "dist" // customize this yourself.
...
}
}
И в вашем package.json:
// package.json
{
"main": "dist/index.js",
"typings": "dist/inde.d.ts",
"files": [
"dist" // customize this yourself.
],
...
}
Вот пример репозитория, в который вы можете заглянуть:
https://github.com/unional/path-equal
Конфигурация моего модуля на самом деле выглядит так, проблема в том, что я не могу импортировать его всеми способами, которые я описал в исходном посте. Я предполагаю, что, возможно, то, что я пытаюсь вывести компилятором, не соответствует спецификации commonjs (?), Но это то, что я хочу, модуль, который я могу импортировать всеми описанными мною способами.
Поскольку вы решили распространять пакет как commonjs, оставьте его как есть и позвольте потребителю использовать его с import x from 'x', когда у них есть esModuleInterop, или import x = require('x'), когда их нет. Не стоит пытаться перехитрить систему. Это просто создаст больше проблем в будущем.
проблема в том, что эти модули не новые, я уже импортирую их в существующие проекты с чем-то вроде import foo from 'foo' из TypeScript, но я также хочу, чтобы другие люди могли писать const foo = require ( 'foo' ) вместо странного const foo = require ( 'foo' ).default. Я не могу просто переписать весь этот импорт, и я не хочу делать резкое изменение основной версии только для этого.
Если вам действительно нужно такое поведение, вы можете сделать это: github.com/Microsoft/TypeScript/issues/… Однако на самом деле это шаг назад. Поскольку вы обновляете свой код до другого синтаксиса модуля, внесите в него критические изменения и позвольте стороне потребления разобраться с этим, IMO. Не усложняйте вещи больше, чем это необходимо. Вы, скорее всего, пожалеете об этом решении в будущем.
Это лучшее, что я мог придумать:
export = Object.assign ( foo, { default: foo } );
Это довольно лаконично, определения типов правильно сгенерированы, и его можно импортировать с помощью всех вышеупомянутых методов.
Сначала вы должны определить, хотите ли вы опубликовать пакет commonjs или пакет esm. Затем вы используете инструменты для создания различных распространяемых материалов.