Как экспортировать модуль TypeScript, чтобы его можно было импортировать как из TypeScript, так и из Node?

Допустим, у вас есть следующий модуль 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;

Есть ли способ лучше?

Сначала вы должны определить, хотите ли вы опубликовать пакет commonjs или пакет esm. Затем вы используете инструменты для создания различных распространяемых материалов.

unional 03.10.2018 23:33

Вы должны использовать esModuleInterop, если хотите, чтобы и import foo, и import * as foo давали вам одно и то же. Это не поведение модуля, совместимого со спецификацией ES.

Aaron Beall 03.10.2018 23:52

@unional Я экспортирую его как пакет commonjs. @Aaron, если я установил esModuleInterop в файле tsconfig.json моего пакета TS, я не вижу изменений в скомпилированном коде, должен ли я экспортировать модуль определенным образом?

Fabio Spampinato 04.10.2018 00:46

В таком случае да, вам не нужен веб-пакет

unional 04.10.2018 00:48
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
1 226
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Насколько мне известно, экспорт и импорт еще не поддерживаются в NodeJS. Проверьте эту статью: node-js-syntaxerror-неожиданный-импорт-токен

И, насколько мне известно, единственный способ использовать синтаксис типов TypeScript - только в файле .ts, поэтому можно скомпилировать необходимые файлы .ts в .js с помощью Babel.

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

Fabio Spampinato 04.10.2018 00:41

Поскольку вы публикуете как пакет 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 (?), Но это то, что я хочу, модуль, который я могу импортировать всеми описанными мною способами.

Fabio Spampinato 04.10.2018 02:05

Поскольку вы решили распространять пакет как commonjs, оставьте его как есть и позвольте потребителю использовать его с import x from 'x', когда у них есть esModuleInterop, или import x = require('x'), когда их нет. Не стоит пытаться перехитрить систему. Это просто создаст больше проблем в будущем.

unional 04.10.2018 02:08

проблема в том, что эти модули не новые, я уже импортирую их в существующие проекты с чем-то вроде import foo from 'foo' из TypeScript, но я также хочу, чтобы другие люди могли писать const foo = require ( 'foo' ) вместо странного const foo = require ( 'foo' ).default. Я не могу просто переписать весь этот импорт, и я не хочу делать резкое изменение основной версии только для этого.

Fabio Spampinato 04.10.2018 02:14

Если вам действительно нужно такое поведение, вы можете сделать это: github.com/Microsoft/TypeScript/issues/… Однако на самом деле это шаг назад. Поскольку вы обновляете свой код до другого синтаксиса модуля, внесите в него критические изменения и позвольте стороне потребления разобраться с этим, IMO. Не усложняйте вещи больше, чем это необходимо. Вы, скорее всего, пожалеете об этом решении в будущем.

unional 04.10.2018 20:54
Ответ принят как подходящий

Это лучшее, что я мог придумать:

export = Object.assign ( foo, { default: foo } );

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

Другие вопросы по теме