Почему для использования класса TypeScript в JavaScript требуется `.default`?

У меня есть класс 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 свойство и зачем оно мне нужно.

Кроме того, все другие ссылки, которые я нашел на эту ошибку, не казались соответствующими тому, что я видел; Я подумал, что документирование этого может помочь кому-то еще, кто сталкивается с подобной ошибкой.

Потому что CommonJS (Node’s require() и exports) не совместим с экспортом по умолчанию ES6. Решение компилировать с понижением, но при этом разрешить работу загрузчикам модулей, совместимым со спецификацией ES6, состоит в том, чтобы выдать __esModule на экспортируемом значении. Бабель делает то же самое. IMO просто избегайте экспорта по умолчанию, они не очень полезны и создают проблемы.

Aaron Beall 01.05.2019 19:38
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
10
1
2 286
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Задний план:

Спецификация языка 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..., он должен работать так, как вы ожидали.

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