Mam kilka plików TypeScript:
MyClass.ts
class MyClass {
constructor() {
}
}
export = MyClass;
MyFunc.ts
function fn() { return 0; }
export = fn;
MyConsumer.ts
import * as MC from './MyClass';
import * as fn from './MyFunc';
fn();
To daje mi błędy podczas próby użycia new
Moduł „MyClass” jest rozpoznawany jako element niebędący modułem i nie można go zaimportować przy użyciu tej konstrukcji.
i kiedy próbujesz zadzwonić fn()
Nie można wywołać wyrażenia, którego typ nie ma podpisu wywołania.
Co daje?
typescript
ecmascript-6
es6-modules
Ryan Cavanaugh
źródło
źródło
javascript
jako podstawowego tagu i pozostawienie goecmascript-6
, ponieważ podstawowy tag tutaj jesttypescript
. Pytanie błędnie zakłada, żeexport =
(funkcja TS) może być sparowanaimport ... from
, podczas gdy powinna być sparowanaimport =
. Jest to w zasadzie import / eksport modułu ES6 vs CJS / AMD.Odpowiedzi:
Dlaczego to nie działa
import * as MC from './MyClass';
To jest
import
składnia w stylu ES6 / ES2015 . Dokładne znaczenie tego to „ Pobierz ładowany obiekt przestrzeni nazw modułu./MyClass
i używaj go lokalnie jakoMC
”. Warto zauważyć, że „ obiekt przestrzeni nazw modułu ” składa się tylko z prostego obiektu z właściwościami. Obiekt modułu ES6 nie może być wywoływany jako funkcja lub znew
.Powiedzieć to jeszcze raz: ES6 nazw moduł obiekt nie może być powoływane jako funkcji lub
new
.To, czego
import
używasz* as X
z modułu, ma tylko właściwości. W CommonJS na niższym poziomie może to nie być w pełni przestrzegane, ale TypeScript mówi ci, jakie jest zachowanie zdefiniowane przez standard.Co działa?
Aby użyć tego modułu, musisz użyć składni importu w stylu CommonJS:
import MC = require('./MyClass');
Jeśli kontrolujesz oba moduły, możesz
export default
zamiast tego użyć :MyClass.ts
export default class MyClass { constructor() { } }
MyConsumer.ts
import MC from './MyClass';
Jestem z tego powodu smutny; Zasady są głupie.
Byłoby miło użyć składni importu ES6, ale teraz muszę to zrobić
import MC = require('./MyClass');
? Tak jest w 2013 roku! Kulawy! Ale żal jest normalną częścią programowania. Proszę przejść do etapu piątego w modelu Kübler-Ross: Akceptacja.TypeScript mówi, że to nie działa, ponieważ nie działa. Istnieją hacki (dodawanie
namespace
deklaracji doMyClass
jest popularnym sposobem udawania, że to działa) i mogą one działać dzisiaj w twoim konkretnym pakiecie modułów obniżających poziom (np. Rollup), ale jest to iluzoryczne. Nie ma jeszcze żadnych implementacji modułów ES6 na wolności, ale nie będzie to wieczne.Wyobraź sobie swoje przyszłe ja, próbując uruchomić na neato natywnej implementacji modułu ES6 i stwierdzając, że naraziłeś się na poważną awarię, próbując użyć składni ES6 do zrobienia czegoś, czego ES6 wyraźnie nie robi .
Chcę skorzystać z mojego niestandardowego modułu ładującego
Może masz moduł ładujący, który „pomocnie” tworzy
default
eksport, gdy żaden nie istnieje. Chodzi mi o to, że ludzie tworzą standardy z jakiegoś powodu, ale ignorowanie standardów jest czasami zabawne i możemy pomyśleć, że to fajna rzecz.Zmień MyConsumer.ts na:
import A from './a';
I określ
allowSyntheticDefaultImports
wiersz polecenia lubtsconfig.json
opcję.Zwróć uwagę, że
allowSyntheticDefaultImports
nie zmienia to w ogóle zachowania kodu w czasie wykonywania. To tylko flaga, która mówi TypeScript, że moduł ładujący moduł tworzydefault
eksport, gdy żaden nie istnieje. Nie sprawi, że Twój kod będzie działał w nodejs w magiczny sposób, jak wcześniej.źródło
export = MyClass
? Moją jedyną opcją jest ustawienie mojego modułucommonjs
i dalsze czynienie świata gorszym miejscem, nie używając nowoczesnego ES?--esModuleInterop
nagłówkiem jest napisane „Zdecydowanie zalecamy stosowanie go zarówno do nowych, jak i istniejących projektów”. Moim zdaniem ta odpowiedź (i wpis / polityka FAQ wDefinitelyTyped
tych linkach) powinna zostać zmodyfikowana, aby odzwierciedlić nowe stanowisko.TypeScript 2.7 wprowadza obsługę, emitując nowe metody pomocnicze: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#support-for-import-d-from-cjs-form- commonjs-modules-with --- esmoduleinterop
Więc w tsconfig.json dodaj te dwa ustawienia:
{ // 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 }
A teraz możesz użyć:
import MyClass from './MyClass';
źródło
esModuleInterop
, użyłemresolveJsonModule
razem z twoją inną sugestią użyciaallowSyntheticDefaultImports
i zadziałało to dla mnie.Dodanie moich 2 centów tutaj na wypadek, gdyby ktoś inny miał ten problem.
Mój sposób na obejście problemu bez modyfikowania
tsconfig.json
(co może być problematyczne w niektórych projektach), po prostu wyłączyłem regułę dla oneline.import MC = require('./MyClass'); // tslint:disable-line
źródło
Wystąpił ten błąd podczas próby dołączenia pakietu debounce npm do mojego projektu.
Kiedy wypróbowałem powyższe rozwiązanie, dostałem wyjątek:
To się skończyło:
import debounce from 'debounce'
źródło