У меня есть класс TypeScript, который является частью пакета npm. Для сопровождения я разбил класс на несколько классов и создал окончательный экспортируемый класс посредством наследования. Я не думаю, что это имеет значение для моего вопроса, но я считаю, что лучше раскрыть эту часть информации. Я определил класс в ChildClass.ts следующим образом:
export default ChildClass extends ParentClass{…}
У Tsc есть outDir "сборка".package.json файл имеет свойство "main": "build/ChildClass.js"
Используя как npm link, так и npm pack, я могу развернуть пакет и без проблем использовать его в демонстрационном пакете TypeScript. Однако, если я попытаюсь использовать пакет в демонстрации JavaScript,
const ChildClass = require('my-package')
const childClass = new ChildClass()
Я получаю ошибкуCannot use 'new' with an expression whose type lacks a call or construct signature.ts(2351)
Если я изменю оператор new, добавив .default следующим образом:
const childClass = new ChildClass.default()
Оно работает. Я понял это, посмотрев на скомпилированный Javascript. Необходимость использовать .default показалась мне неразумной, чтобы ожидать, что (гипотетические) потребители JavaScript моего пакета будут знать. Я также обнаружил, что если я избегаю export default и просто использую export, то пакет работает более предсказуемо, что я и сделал. Теперь я могу использовать
const {ChildClass} = require('my-package')
const childClass = new ChildClass()
и аналогичный синтаксис
import {ChildClass} from 'my-package'
const childClass = new ChildClass()
в машинописи.
Все-таки хотелось бы узнать, что это за волшебное .default свойство и зачем оно мне нужно.
Кроме того, все другие ссылки, которые я нашел на эту ошибку, не казались соответствующими тому, что я видел; Я подумал, что документирование этого может помочь кому-то еще, кто сталкивается с подобной ошибкой.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Спецификация языка ECMAScript указанный указывает, что экспортируемое имя export default — это просто "default". Так что вы можете думать об этом как об обычном экспорте с именем "default".
Компиляция модуля ES6 в CommonJS имеет только стандарт де-факто, так как Спецификация языка ECMAScript никогда не упоминала об этом. В настоящее время транспиляторы (TypeScript и Babel) просто помещают весь экспорт в module.exports, где экспорт по умолчанию больше не является особенным.
Только когда потребители также понимают вышеуказанный «стандарт» (например, TypeScript, Babel и Webpack), они преобразуют import ChildClass from 'my-package операторы в const ChildClass = require('my-package').default для вас. Конечно, Node.js занимается модулями CommonJS и ES6 отдельно и не занимается этим.
(На самом деле это сложнее, потому что Babel смешал import DefaultExport from 'some-package' и import * as AllExports from 'some-package, современные потребители модулей должны попробовать оба)
TypeScript имеет специальный синтаксисexport = для работы с традиционными потребителями CommonJS (это не в JavaScript). Если вы измените свой export default class ChildClass... на export = class ChildClass..., он должен работать так, как вы ожидали.
Потому что CommonJS (Node’s
require()иexports) не совместим с экспортом по умолчанию ES6. Решение компилировать с понижением, но при этом разрешить работу загрузчикам модулей, совместимым со спецификацией ES6, состоит в том, чтобы выдать__esModuleна экспортируемом значении. Бабель делает то же самое. IMO просто избегайте экспорта по умолчанию, они не очень полезны и создают проблемы.