Почему ссылка на неэкспортированный класс не генерирует ошибку переноса?

#typescript #ecmascript-6 #module #tsc #tsconfig

#typescript #ecmascript-6 #модуль #tsc #tsconfig

Вопрос:

Я относительно новичок как в Typescript, так и в Javascript (и node.js ), с опытом работы на Java, но быстро учится болезненным способом. Недавно я преобразовал один гигантский файл Typescript с несколькими классами в использование нескольких классов. Это потребовало некоторого исследования, и я не утверждаю, что полностью понимаю 2 различные системы импорта Javascript. Но я использую import {ClassName} from './{Classname}' синтаксис и слежу за тем Classname , чтобы он начинался с export class ClassName . Изначально это работало отлично. В частности, исходя из фона Java и завися от ошибок компилятора, я оценил, что Netbeans обнаружит ошибки при моем импорте, и tsc согласился. Добавьте импорт, повторите попытку, и все обрело смысл.

Пока он не перестал работать, то есть ошибки не были сгенерированы с неправильным (?) кодом. Во время выполнения я получил ReferenceError: ClassToBeImportedis not defined . Конечно же, ClassToBeImported не импортировался. Я ожидаю, что добавление import {ClassToBeImported} from './{ClassToBeImported} решит эту проблему. (Я прав? В этом случае легче ответить, чем протестировать.) Что меня беспокоит, так это то, что на этот раз это была ошибка времени выполнения, а не ошибка IDE / transpiler.

Пытаясь придумать минимальный пример, я думаю, проблема в том, что файл, на который ссылается ссылка, не экспортировался. Если я добавляю / удаляю export из export class NeedsToBeImported , ошибка появляется / исчезает соответственно.

Это приведет к появлению ошибки ( Cannot find name 'ClassToBeImported'. ):

 // in file MainClass.ts
export class MainClass{
    constructor(){
        let x = ClassToBeImported.SOME_FIELD;
    }
}

// in file ClassToBeImported.ts, same folder
export class ClassToBeImported{
    static SOME_FIELD : string = "data";
}
  

Этого не произойдет, пока время выполнения:

 // in file MainClass.ts
export class MainClass{
    constructor(){
        let x = ClassToBeImported.SOME_FIELD;
    }
}

// in file ClassToBeImported.ts, same folder
class ClassToBeImported{
    static SOME_FIELD : string = "data";
}
  

Итак, основной вопрос заключается в том, что, черт возьми, происходит. («Почему ссылка на неэкспортированный класс не генерирует ошибку переноса?») Второй вопрос заключается в том, могу ли я что-нибудь сделать, чтобы сделать это «безопаснее» для себя. Если есть какая-то опция, которую я могу включить tsconfig.json (в настоящее время ориентирована на es2015), чтобы сделать ее более строгой, это может быть полезно.

Комментарии:

1. какую версию typescript вы используете?

2. Если вам не хватает export , TSC, вероятно, не распознается ClassToBeImported.ts как модуль. И как сценарий, class ClassToBeImported это глобальный, поэтому он работает нормально. Вам просто нужно включить скрипт на свою страницу вместе с другими.

3. @shusson На самом деле я не уверен. tsc --version возвращает 2.6.1, но 3.4.2 находится в моем package.json.

Ответ №1:

В JavaScript и TypeScript есть два типа исходных файлов: скрипты и модули.

Я цитирую руководство:

В TypeScript, как и в ECMAScript 2015, любой файл, содержащий import или верхнего уровня export , считается модулем. И наоборот, файл без каких-либо объявлений верхнего уровня import или export рассматривается как скрипт, содержимое которого доступно в глобальной области видимости (и, следовательно, также для модулей).

Например, вы можете загрузить файл ClassToBeImported.js в <script> теге на веб-странице, и тогда ClassToBeImported класс будет доступен как глобальная переменная.