Typescript es6 içe aktarma modülü "Dosya bir modül hatası değil"


127

Typcript 1.6 es6 modülleri sözdizimi ile kullanıyorum.

Dosyalarım:

test.ts:

module App {
  export class SomeClass {
    getName(): string {
      return 'name';
    }
  }
}

main.ts:

import App from './test';

var a = new App.SomeClass();

main.tsDosyayı derlemeye çalıştığımda şu hatayı alıyorum:

Hata TS2306: 'test.ts' dosyası bir modül değil.

Bunu nasıl başarabilirim?


Bu sorunu yaşadım, sınıfta
kurucum

Yanıtlar:


139

Genişletilmiş - bazı yorumlara dayalı olarak daha fazla ayrıntı sağlamak için

Hata

Hata TS2306: 'test.ts' dosyası bir modül değil.

Burada http://exploringjs.com/es6/ch_modules.html açıklanan olgudan gelmektedir.

17. Modüller

Bu bölüm yerleşik modüllerin ECMAScript 6'da nasıl çalıştığını açıklar.

17.1 Genel Bakış

ECMAScript 6'da modüller dosyalarda saklanır. Dosya başına tam olarak bir modül ve modül başına bir dosya vardır. Bir modülden bir şeyleri dışa aktarmanın iki yolu var. Bu iki yol karıştırılabilir, ancak genellikle ayrı ayrı kullanmak daha iyidir.

17.1.1 Birden çok adlandırılmış dışa aktarma

Birden çok adlandırılmış dışa aktarma olabilir:

//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}
...

17.1.2 Tek varsayılan dışa aktarma

Tek bir varsayılan dışa aktarma olabilir. Örneğin, bir işlev:

//------ myFunc.js ------
export default function () { ··· } // no semicolon!

Yukarıdakilere dayanarak export, test.js dosyasının bir parçası olarak ihtiyacımız var . İçeriğini şu şekilde ayarlayalım:

// test.js - exporting es6
export module App {
  export class SomeClass {
    getName(): string {
      return 'name';
    }
  }
  export class OtherClass {
    getName(): string {
      return 'name';
    }
  }
}

Ve şimdi onu şu üç yolla içe aktarabiliriz:

import * as app1 from "./test";
import app2 = require("./test");
import {App} from "./test";

Ve şu şekilde ithal edilen şeyleri tüketebiliriz:

var a1: app1.App.SomeClass  = new app1.App.SomeClass();
var a2: app1.App.OtherClass = new app1.App.OtherClass();

var b1: app2.App.SomeClass  = new app2.App.SomeClass();
var b2: app2.App.OtherClass = new app2.App.OtherClass();

var c1: App.SomeClass  = new App.SomeClass();
var c2: App.OtherClass = new App.OtherClass();

ve eylem halinde görmek için yöntemi çağırın:

console.log(a1.getName())
console.log(a2.getName())
console.log(b1.getName())
console.log(b2.getName())
console.log(c1.getName())
console.log(c2.getName())

Orijinal kısım, ad alanının kullanımındaki karmaşıklık miktarını azaltmaya yardımcı olmaya çalışıyor

Orijinal bölüm:

Bu soru ve cevapları kontrol etmenizi şiddetle öneririm:

TypeScript harici modülleri ile ad alanlarını nasıl kullanırım?

İlk cümleyi aktarmama izin verin:

Harici modüllerde "ad alanları" kullanmayın.

Bunu yapma.

Ciddi anlamda. Dur.

...

Bu durumda sadece moduleiçine ihtiyacımız yok test.ts. Bu, ayarlanan içeriği olabilir test.ts:

export class SomeClass
{
    getName(): string
    {
        return 'name';
    }
}

Daha fazlasını buradan okuyun

İhracat =

Önceki örnekte, her doğrulayıcıyı tükettiğimizde, her modül yalnızca bir değer dışa aktarıyordu. Bu gibi durumlarda, tek bir tanımlayıcı da işe yarayacaksa, bu sembollerle nitelikli isimleriyle çalışmak zahmetlidir.

export =Söz dizimi belirtir modülden dışa tek bir nesne . Bu bir sınıf, arabirim, modül, işlev veya enum olabilir. İçe aktarıldığında, dışa aktarılan sembol doğrudan tüketilir ve herhangi bir adla nitelenmez.

daha sonra şu şekilde tüketebiliriz:

import App = require('./test');

var sc: App.SomeClass = new App.SomeClass();

sc.getName();

Daha fazlasını buradan okuyun:

İsteğe Bağlı Modül Yükleme ve Diğer Gelişmiş Yükleme Senaryoları

Bazı durumlarda, yalnızca bazı koşullar altında bir modül yüklemek isteyebilirsiniz. TypeScript'te, tip güvenliğini kaybetmeden modül yükleyicileri doğrudan çağırmak için bunu ve diğer gelişmiş yükleme senaryolarını uygulamak için aşağıda gösterilen modeli kullanabiliriz.

Derleyici, her modülün yayınlanan JavaScript'te kullanılıp kullanılmadığını algılar. Sadece tip sistemin bir parçası olarak kullanılan modüller için, herhangi bir gerekli çağrı verilmez. Kullanılmayan referansların bu şekilde ayrılması, iyi bir performans optimizasyonudur ve bu modüllerin isteğe bağlı olarak yüklenmesine de izin verir.

Modelin ana fikri, import id = require ('...') ifadesinin bize harici modül tarafından sunulan tiplere erişim sağlamasıdır. Modül yükleyici, aşağıdaki if bloklarında gösterildiği gibi dinamik olarak çağrılır (zorunlu olarak). Bu, referans ayırma optimizasyonundan yararlanır, böylece modül yalnızca ihtiyaç duyulduğunda yüklenir. Bu kalıbın çalışması için, içe aktarma yoluyla tanımlanan sembolün yalnızca tür konumlarında kullanılması (yani asla JavaScript'e gönderilecek bir konumda olmaması) önemlidir.


1
Ancak bu: Uygulamayı içe aktar = gerekli ('./ test'); es6 modüllerinin sözdizimi değildir. bu ortak js. Es6 modül sözdizimi ile yapabilir miyim?
Bazinga

@JsIsAwesome JS modüllerini Typescript modülleriyle karıştırmaya çalışıyorsunuz. İkisinin karışımını değil, birini veya diğerini kullanmanız gerekir.
JJJ

Bu cevap ES6 sözdizimine atıfta bulunmuyor
phiresky

@phiresky, ne demek istiyorsun?
Radim Köhler

1
Teşekkürler, bu harika.
phiresky

24

Yukarıdaki cevaplar doğrudur. Ama her ihtimale karşı ... VS Code'da aynı hatayı aldım. Hata veren dosyayı yeniden kaydetmek / yeniden derlemek gerekiyordu.


3
Bu benim için çalıştı. Bir noktalı virgülü kaldırdım, yeniden ekledim ve dosyayı yeniden kaydettim ve ardından Webpack'i çalıştırdım. Yaşamak için harika bir zaman.
Ray Hogan

1
Webstorm'a alıştım ve dosyaların VS Code'da otomatik olarak kaydedilmediğini fark etmedim. Bu cevap beni çok acıdan kurtardı, teşekkürler.
cib

VS Code'da otomatik kaydetme için bir ayar vardır. Bunu kullanmıyorum çünkü VS Code zaten kaydedilmemiş dosyaları yedekliyor ve her zaman git kullanmıyorum.
2019

13

Bunu nasıl başarabilirim?

Örneğiniz , artık ad alanı olarak adlandırılan TypeScript <1.5 dahili modülü bildiriyor . Eski sözdizimi artık eşdeğerdir . Sonuç olarak, aşağıdakiler çalışır:module App {}namespace App {}

// test.ts
export namespace App {
    export class SomeClass {
        getName(): string {
            return 'name';
        }
    }
}

// main.ts
import { App } from './test';
var a = new App.SomeClass();

Söyleniyor ki...

Ad alanlarını dışa aktarmamaya çalışın ve bunun yerine modülleri dışa aktarın (önceden harici modüller olarak adlandırılırdı ). Gerekirse, aşağıdaki gibi ad alanı içe aktarma modeliyle içe aktarmada bir ad alanı kullanabilirsiniz :

// test.ts
export class SomeClass {
    getName(): string {
        return 'name';
    }
}

// main.ts
import * as App from './test'; // namespace import pattern
var a = new App.SomeClass();

1
Hala iyi bir uygulama mı? Bu yanıta göre ( stackoverflow.com/a/35706271/2021224 ), bunun gibi bir işlevi veya sınıfı içe aktarmaya ve sonra onu çağırmaya çalışmak - "ES6 özelliklerine göre yasa dışıdır".
Andrey Prokhorov

2

A. Tim'in cevabına ek olarak , bunun bile işe yaramadığı zamanlar vardır, bu yüzden yapmanız gerekenler:

  1. İçe aktarma dizesini intellisense kullanarak yeniden yazın. Bazen bu sorunu düzeltir
  2. VS Kodunu yeniden başlatın

1
stackblitz için de aynı - modülü içe aktaran yeniden derlenmiş dosya ve her
şey yolunda

Bunu kodum doğru biçimlendirilmediğinde de yaşadım. VSCode, sınıflarımı kendi dosyalarına ayırırken kopyala + yapıştır sınıf kodumu girintiledi ve VSCode export class... {, bundan sonra her şeyi girintiledi , bu da angular'ın hoşlanmadığı bu sorunu bana verdi. Biçimlendirmeyi düzelttikten sonra sorunsuz bir şekilde derlendi.
Guy Park

0

Tim'in cevabına ek olarak, bu sorun benim için bir dosyayı yeniden düzenlerken, kendi dosyalarına ayırırken ortaya çıktı.

VSCode, bazı nedenlerden dolayı, [sınıf] kodumun bazı kısımlarını girintili oluşturdu ve bu soruna neden oldu. Bunu ilk başta fark etmek zordu, ancak kodun girintili olduğunu fark ettikten sonra kodu formatladım ve sorun ortadan kalktı.

örneğin, Sınıf tanımının ilk satırından sonraki her şey yapıştırma sırasında otomatik olarak girintilendi.

export class MyClass extends Something<string> {
    public blah: string = null;

    constructor() { ... }
  }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.