Ошибка дублирования идентификатора с файлом d.ts и nodejs требуют с тем же именем

#javascript #node.js #typescript #tsc

#javascript #node.js #typescript #tsc

Вопрос:

Теперь я уверен, что проблема связана с тем, что включен файл d.ts, который содержит модуль с именем «Shared», и оператор require, который включает переменную с тем же именем, если она используется в среде NodeJS.

 // shared.d.ts
declare module Shared { ... }

// other_module.ts
/// <reference path="shared.d.ts"/>
if(require) { var Shared = require("shared"); }
export class Something {
    public someVar = new Shared.SomethingElse("blah");
}
  

Поэтому, когда я компилирую other_module.ts (что на самом деле представляет собой множество отдельных файлов), он сообщает мне, что Shared — это дублированный идентификатор, который я могу понять, поскольку TS считает, что Shared — это модуль, но затем ему сообщают, что это возврат require .

Проблема здесь в том, что выходные данные модулей должны быть совместимы с системой require NodeJS, поэтому в этом случае, когда требуется other_module, он будет находиться в своей собственной области видимости и не будет знать, о Shared.SomethingElse чем требуется require, поэтому внутренние модули в other_module смогут получить доступ к общей библиотеке, но всреда браузера, которую он получит Shared.SomethingElse через глобальную область.

Если я удалю ссылку, файл не будет компилироваться, поскольку он не знает об Shared этом, если я удалю require при загрузке модуля в nodejs ( var otherModule = require("other_module") ), он будет жаловаться, что он не знает Shared . Итак, есть ли способ решить эту проблему?

Ответ №1:

Сначала ошибка

Дубликат идентификатора, потому что у вас есть Shared in shared.d.ts in other_module.ts .

ИСПРАВЬТЕ A, будьте все внешними

Если вы хотите использовать amd / commonjs ie. вам нужно использовать внешние модули import/require (не так, var/require как вы делаете). Использование an import создает новое пространство объявления переменных, и поэтому вы больше не загрязняете глобальное пространство Shared other_module.ts имен. Короче говоря :

 // shared.d.ts
declare module Shared { 
   export function SomethingElse(arg:string):any;
}
declare module 'shared'{ 
    export = Shared; 
}
  

И типизированный импорт:

 // other_module.ts

/// <reference path="shared.d.ts"/>
import Shared = require("shared"); 

export class Something {
    public someVar = new Shared.SomethingElse("blah");
}
  

ИСПРАВЬТЕ B, как и раньше, но тогда вам нужно использовать другое имя

Внутри other_module не используйте имя Shared локально, если локальная область является глобальной областью. Я рекомендую вам просто использовать external везде и компилировать для узла с commonjs и браузера с amd , как показано в исправлении A, но если вам нужно, здесь исправлена компиляция other_module.ts .

 // other_module.ts
/// <reference path="shared.d.ts"/>
var fooShared: typeof Shared;
if(require) {  fooShared = require("shared"); }
else { fooShared = Shared; } 
export class Something {
    public someVar = new fooShared.SomethingElse("blah");
}
  

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

1. проблема в том, что мне нужно загрязнить глобальное пространство имен для использования в браузере, сценарий в основном представляет собой контракт данных на веб-сервис, который совместно используется сервером и клиентом. Поэтому я просто хочу 1 набор классов, которые можно использовать с обеих сторон. Итак, я попытался написать его таким образом, чтобы, если require etc доступен, он использовал это, в противном случае он просто полагается на то, что глобальные переменные находятся на месте. Если бы я должен был перейти по маршруту импорта, мне нужно использовать загрузчики модулей в браузере, что не так. Также для использования import Shared мне нужно использовать export module в общей библиотеке, но это МНОГО файлов.

2. Ах! ваш пример B кажется, что это сработает, попробует это и сообщит 1 для идей в любом случае.

3. Кажется, работает, так что это должно помочь мне преодолеть этот горб, по крайней мере, спасибо за помощь.