Что означает "... разрешается в немодульную сущность и не может быть импортировано с помощью этой конструкции"?


у меня есть некоторые файлы машинописи:

MyClass.ТС

class MyClass {
  constructor() {
  }
}
export = MyClass;

MyFunc.ТС

function fn() { return 0; }
export = fn;

MyConsumer.ТС

import * as MC from './MyClass';
import * as fn from './MyFunc';
fn();

это дает мне ошибки при попытке использовать new

модуль "MyClass" разрешается в немодульную сущность и не может быть импортирован с помощью этой конструкции.

и при попытке вызова fn()

не может ссылаться на выражение, тип которого не имеет подписи вызова.

что это дает?

4 62

4 ответа:

почему это не работает

import * as MC from './MyClass';

это ES6 / ES2015-style import синтаксис. Точное значение этого- " возьмите модуль объект пространства имен загрузить из ./MyClass и использовать его локально как MC". Примечательно ,что " модуль объект пространства имен " состоит только из простого объекта со свойствами. Объект модуля ES6 не может быть вызван как функция или с помощью new.

сказать это снова: объект пространства имен модуля ES6 не может вызывается как функция или с помощью new.

что ты import используя * as X из модуля определяется только свойствами. В downleveled CommonJS это может быть не полностью соблюдено, но TypeScript говорит вам, какое поведение определяется стандартом.

что работает?

вам нужно будет использовать синтаксис импорта CommonJS-style, чтобы использовать этот модуль:

import MC = require('./MyClass');

если вы контролируете оба модуля, вы можете использовать export default вместо:

MyClass.ТС

export default class MyClass {
  constructor() {
  }
}

MyConsumer.ТС

import MC from './MyClass';

мне грустно об этом; правила тупые.

было бы неплохо использовать синтаксис импорта ES6, но теперь я должен сделать это import MC = require('./MyClass'); вещь? Это так 2013! Хромой! Но горе-это нормальная часть программирования. Пожалуйста, перейдите к пятому этапу в модели Кюблера-Росса: принятие.

TypeScript здесь говорит вам, что это не так работа, потому что она не работает. Есть хаки (добавление namespace декларации MyClass это популярный способ сделать вид, что это работает), и они может работайте сегодня в вашем конкретном модуле понижающего уровня bundler (например, rollup), но это иллюзорно. В дикой природе пока нет никаких реализаций модуля ES6, но это не будет вечно.

представьте себе свое будущее, пытаясь запустить реализацию модуля neato native ES6 и обнаружив, что вы настроили себя за крупный провал по попытка использовать синтаксис ES6, чтобы сделать то, что ES6 явно не делает.

я хочу воспользоваться моим нестандартным загрузчиком модулей

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

изменить MyConsumer.ТС к:

import A from './a';

и указать или .

обратите внимание, что allowSyntheticDefaultImports не изменять поведение во время выполнения вашего кода. Это просто флаг, который сообщает TypeScript, что ваш загрузчик модулей создает default экспорт, когда ни один не существует. Это не будет волшебным образом заставить ваш код работать в nodejs, когда это не было раньше.

TypeScript 2.7 вводит поддержку путем создания новых вспомогательных методов: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#support-for-import-d-from-cjs-form-commonjs-modules-with---esmoduleinterop

Так в tsconfig.json добавить эти два параметра:

{
    // Enable support for importing CommonJS modules targeting es6 modules
    "esModuleInterop": true,

    // When using above interop will get missing default export error from type check since
    // modules use "export =" instead of "export default", enable this to ignore errors.
    "allowSyntheticDefaultImports": true
}

и теперь вы можете использовать:

import MyClass from './MyClass';

добавление моих 2 центов здесь упаковывает кого-то еще в эту проблему.

мой способ обойти проблему без изменения tsconfig.json (Что может быть проблематично в некоторых проектах), я пошел с простым отключением правила для oneline.

import MC = require('./MyClass'); // tslint:disable-line

Я получил эту ошибку при попытке включить пакет NPM debounce в мой проект.

когда я попробовал принятое решение выше, я получил исключение:

назначение импорта не может использоваться при таргетинге на модули ECMAScript. Рассмотрите возможность использования 'импорт * как НС из "мод"', 'импорт {а} от "Мод"', 'импорт d из "mod"', или другой формат модуля вместо этого.

это в конечном итоге работает:

import debounce from 'debounce'