Подтвердить что ты не робот

Typescript Модуль импорта es6 "Файл не является ошибкой модуля"

Я использую typescript 1.6 с синтаксисом модулей es6.

Мои файлы:

test.ts:

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

main.ts:

import App from './test';

var a = new App.SomeClass();

Когда я пытаюсь скомпилировать файл main.ts, я получаю эту ошибку:

Ошибка TS2306: файл test.ts не является модулем.

Как я могу это сделать?

4b9b3361

Ответ 1

Расширенные - чтобы предоставить более подробную информацию на основе некоторых комментариев

Ошибка

Ошибка TS2306: Файл test.ts не является модулем.

Исходит из описанного здесь факта http://exploringjs.com/es6/ch_modules.html

17. Модули

В этой главе объясняется, как встроенные модули работают в ECMAScript 6.

17.1 Обзор

В ECMAScript 6 модули хранятся в файлах. Существует ровно один модуль на файл и один файл на модуль. У вас есть два способа экспортировать вещи из модуля. Эти два способа могут быть смешаны, но это обычно лучше использовать их отдельно.

17.1.1 Множественный экспорт названий

Может быть несколько именованных экспорт:

//------ 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 Отдельный экспорт по умолчанию

Может быть один экспорт по умолчанию. Например, функция:

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

На основании вышеизложенного нам нужен export, как часть файла test.js. Позвольте отрегулировать его содержимое следующим образом:

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

И теперь мы можем импортировать его с помощью следующих способов:

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

И мы можем использовать импортированные вещи следующим образом:

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();

и вызовите метод, чтобы увидеть его в действии:

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

Оригинальная часть пытается помочь уменьшить объем сложности в использовании пространства имен

Исходная часть:

Я бы настоятельно рекомендовал проверить эти Q и A:

Как использовать пространства имен с TypeScript внешними модулями?

Позвольте мне привести первое предложение:

Не используйте "пространства имен" во внешних модулях.

Не делайте этого.

Серьезно. Стоп.

...

В этом случае нам просто не нужно module внутри test.ts. Это может быть содержание его настроено test.ts:

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

Подробнее здесь

Export =

В предыдущем примере, когда мы потребляли каждый валидатор, каждый модуль экспортировал только одно значение. В подобных случаях громоздко работать с этими символами через их квалифицированное имя, когда один идентификатор будет делать то же самое.

Синтаксис export = указывает один объект, который экспортируется из модуля. Это может быть класс, интерфейс, модуль, функция или перечисление. При импорте экспортируемый символ потребляется напрямую и не подлежит никакому имени.

мы можем позже использовать его следующим образом:

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

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

sc.getName();

Подробнее здесь:

Дополнительные загрузки модулей и другие расширенные сценарии загрузки

В некоторых случаях вы можете захотеть загрузить модуль только в некоторых условиях. В TypeScript мы можем использовать шаблон, показанный ниже, для реализации этого и других расширенных сценариев загрузки для непосредственного вызова загрузчиков модулей без потери безопасности типа.

Компилятор определяет, используется ли каждый модуль в испускаемом JavaScript. Для модулей, которые используются только как часть системы типов, не требуются вызовы. Это отбраковка неиспользуемых ссылок - хорошая оптимизация производительности, а также возможность дополнительной загрузки этих модулей.

Основная идея шаблона заключается в том, что оператор import id = require ('...') дает нам доступ к типам, открытым внешним модулем. Загрузчик модуля вызывается (через требование) динамически, как показано в блоках if ниже. Это упрощает оптимизацию ссылок, так что модуль загружается только тогда, когда это необходимо. Чтобы этот шаблон работал, важно, чтобы символ, определенный с помощью импорта, использовался только в позициях типа (т.е. Никогда в позиции, которая не была бы выбрана в JavaScript).

Ответ 2

Как я могу это сделать?

В этом примере объявляется TypeScript < 1.5, который теперь называется namespace. Старый синтаксис 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();

Это сказано...

Попробуйте избежать экспорта пространств имен и вместо этого экспортируйте модули (которые ранее назывались внешними модулями). В случае необходимости вы можете использовать пространство имён при импорте с шаблоном импорта пространства имен следующим образом:

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

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

Ответ 3

Выше ответы верны. Но на всякий случай... Получил ту же ошибку в VS Code. Пришлось заново сохранить/перекомпилировать файл, который выдавал ошибку.

Ответ 4

В дополнение к ответу А. Тима бывают случаи, когда даже это не работает, поэтому вам необходимо:

  1. Перепишите строку импорта, используя intellisense. Иногда это решает проблему
  2. Перезапустите VS Code

Ответ 5

перекомпиляция кода, т.е. выполнение ng-serve мне помогло.

Ответ 6

В дополнение к ответу Тима, эта проблема возникла у меня, когда я разделял рефакторинг файла, разделяя его на свои собственные файлы.

VSCode, по какой-то причине, выделил части моего кода [класса], что вызвало эту проблему. Сначала это было трудно заметить, но после того, как я понял, что код отступ, я отформатировал код и проблема исчезла.

например, все после первой строки определения класса автоматически вставлялось при вставке.

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

    constructor() { ... }
  }