Совместное использование файла между commonjs и ejs, Typescript не является модулем .ts (2306) в файле commonjs

Фон

У меня есть файл, которым мне нужно поделиться между двумя репозиториями. Файл содержит один-единственный объект.

  • Repo A настроен на прием только файлов commonjs (require("/path/to/file")), и мне нелегко получить доступ к его конфигурациям babel.
  • Репо B использует стиль импорта ES6 import foo from "bar", и я могу поиграть с его tsconfig.json.

Я знаю, что если я использую modules.export = myObject, он работает только для репо commonjs (репо A), а если я использую export = myObject или export default myObject, он работает только для репо ES6 (репо B).

Вопросов:

  1. Можно ли заставить один и тот же файл работать в обеих системах? Я пробовал export = modules.export = myObject или любую другую комбинацию, но ничего не работает.

  2. Как мне импортировать версию commonjs в репозиторий ES6? Я попытался оставить это файл commonjs modules.export = myObject, но в репо B, когда я делаю import foo from "path/to/file", он продолжает выкрикивать следующее сообщение. он уходит в тот момент, когда я меняю его на export = myObject, но тогда он не будет работать для Repo A.

File '/path/to/file.ts' is not a module.ts(2306)

Примечания

  1. Я обнаружил, что параметр "esModuleInterop": true в моем tsconfig.json должен заставить его работать, но независимо от того, что я делаю (любое значение "module" в tsconfig.json , включаю allowSyntheticDefaultImports) не работает. У меня все та же ошибка 2306.
  2. Как я уже упоминал в комментарии, можно считать, что файл содержит статический объект. (например, {a: 5, b: 8};)

tsconfig.json

Часть репо A, к которой я прикасаюсь, - это конфигурация файл для Quasar, и он на ванильном JS.

Репо B - это проект Typescript / Node, и соответствующая часть tsconfig.json в нем:

"compilerOptions": {
        "baseUrl": ".",
        "esModuleInterop": true,
        "experimentalDecorators": true,
        "module": "commonjs",
        "moduleResolution": "node",
        "outDir": "dist",
        "strict": true,
        "sourceMap": true,
        "target": "es6",
        ...

person Aidin    schedule 04.02.2021    source источник
comment
Показать общий файл   -  person Aluan Haddad    schedule 04.02.2021
comment
@AluanHaddad полагает, что это просто { a: 5, b: 8}. Итак, module.exports = { a: 5, b: 8 }; (весь файл представляет собой только эту строку) работает только для commonjs, а export default { a: 5, b: 8}; - только для es6.   -  person Aidin    schedule 04.02.2021
comment
Вы можете поделиться своим tsconfig.json?   -  person Federkun    schedule 10.02.2021
comment
Только что добавил @federkun.   -  person Aidin    schedule 11.02.2021


Ответы (3)


Я только что обнаружил, что если файл является .json файлом с правильным форматом JSON, его можно использовать как в ES6 (import), так и в CommonJS (require).

Согласно этому ответуэта статья), для ES6 вам нужно включить "resolveJsonModule": true, в tsconfig.json, и тогда вы можете иметь контент в обоих форматах.

Итак, если файл content.json имеет следующее содержимое (без комментариев или чего-либо еще):

{
   "age": 34
}

тогда у нас будет ...

import * as jsonContent from "../../content.json"

console.log(jsonContent.age); // prints out 34

а также

const jsonContent = require("../../content.json");

console.log(jsonContent.age); // prints out 34

Они оба успешно распечатывают контент!

person Aidin    schedule 12.05.2021

Я нашел решение, однако синтаксис импорта в мире commonjs не самый приятный, но я надеюсь, что он вам пригодится.

Вы не предоставили никакой информации о том, как настраиваются ваши проекты, кроме указания импорта в стиле commonjs и es6, поэтому я здесь рискую. Также стоит отметить, что при включении файлов работало, при использовании импорта в стиле commonjs они были набраны, а не сохранены их типы машинописного текста (мне не удалось набрать текст с использованием импорта в стиле commonjs (требуется) - я не использовал этот импорт синтаксис на некоторое время, поэтому правильные параметры tsconfig.json, чтобы заставить его работать, ускользнули от меня).


Я переместил общий код в собственный проект и скомпилировал его со следующими настройками tsconfig:

Общий tsconfig.json:

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "ES5",
        "lib": [ "ES5" ],
    }
}

Shared.ts:

export default {'a': 1, 'b': 2};

Shared.js (вывод):

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = { 'a': 1, 'b': 2 };

(Обратите внимание, что этот вывод выполнен в стиле commonjs, потому что ES6 совместим с файлами commonjs).


При использовании require напрямую вам необходимо указать переменную .default в импортированном файле:

commonjs.ts

var val = require("../shared/shared").default;

console.log(val);

Однако, если вы настроены так, что можете писать импорт и вывод в стиле ES6 в commonjs, вы можете вместо этого использовать следующий синтаксис (это предоставит вам информацию для ввода):

commonjs.ts

import val from "../shared/shared";

console.log(val);

Оба вышеуказанных файла были скомпилированы с использованием следующего tsconfig:

tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "lib": [ "es5" ],
        "types": ["node"]
    }
}

Импорт ES6 довольно прост:

es6.ts

import shared from "../shared/shared";

console.log(shared);

tsconfig.json:

{
    "compilerOptions": {
        "module": "ES6",
        "target": "es6",
        "lib": [ "es6" ]
    }
}

У меня есть скрытое подозрение, что это не на 100% решает вашу проблему, но мне понадобятся ваши настройки tsconfig для каждого проекта в качестве версии компилятора машинописного текста, который вы используете для каждого проекта, чтобы дать более точный ответ.

person Griffork    schedule 10.02.2021

Я немного поэкспериментировал и сделал другое решение, которое вы могли бы предпочесть.

Я до сих пор не понял, как набирать текст при импорте в стиле common-js, но импорт работает при запуске и не вызывает ошибок компилятора.


Я переместил общий код в собственный проект и скомпилировал его в другой каталог. Это связано с тем, что флаг esModuleInterop не работает при импорте файла машинописного текста, поэтому вместо этого я скомпилировал файл javascript с поддерживающим файлом .d.ts в другой каталог, чтобы исходный файл .ts не вызывал конфликта.

Общий tsconfig.json:

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "ES5",
        "lib": [ "ES5" ],
        "declaration": true,
        "outDir": "../sharedOut"
    }
}

Shared.ts:

export = {'a': 1, 'b': 2};

И в выходной папке у вас должно получиться:

Shared.js:

"use strict";
module.exports = { 'a': 1, 'b': 2 };

Shared.d.ts

declare const _default: {
    a: number;
    b: number;
};
export = _default;

В результате импорт commonjs будет выглядеть так:

commonjs.ts

var val = require("../sharedOut/shared");

console.log(val);

или (если вы можете использовать импорт в стиле ES6, но хотите, чтобы вывод был commonjs):

import val from "../sharedOut/shared";

console.log(val);

Оба вышеуказанных файла были скомпилированы с использованием следующего tsconfig:

tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "lib": [ "es5" ],
        "types": ["node"],
        "esModuleInterop": true
    }
}


Импорт ES6 (снова) довольно прост:

es6.ts

import shared from "../shared/shared";

console.log(shared);

tsconfig.json:

{
    "compilerOptions": {
        "module": "ES6",
        "target": "es6",
        "lib": [ "es6" ],
        "esModuleInterop": true
    }
}


Опять же, если это не решит вашу проблему, мне понадобится дополнительная информация для прогресса. Мне потребуются ваши настройки tsconfig для каждого проекта в качестве версии компилятора машинописного текста, который вы используете для каждого проекта, чтобы дать более точный ответ.

person Griffork    schedule 10.02.2021
comment
Я дал этот ответ, основываясь на ответе на этот вопрос: stackoverflow.com/questions/56238356/ - person Griffork; 10.02.2021
comment
Спасибо за время, которое вы потратили на этот @griffork. К сожалению, tsconfig.json не разделяется между репозиториями, и на самом деле один из них находится в ванильном JS. Я включил tsconfig.json в репо B, на случай, если вы захотите взглянуть. - person Aidin; 11.02.2021
comment
Без проблем! Кстати, ни один из tsconfigs не используется в моих ответах, я предоставляю ts-конфигурации, потому что вам нужна эта информация, чтобы выбрать, какое решение подойдет вам. Я считаю, что вам понадобится отдельный tsconfig для общего файла, и вам нужно будет предварительно скомпилировать файл перед включением в оба проекта, если вы используете это решение. Если вы используете другой мой ответ, вам нужно будет только предварительно скомпилировать файл для проекта javascript и изменить требуемые вызовы для ссылки на свойство .default. Проект ts должен иметь возможность напрямую включать файл ts ... - person Griffork; 12.02.2021
comment
В обоих ответах есть прямые решения javascript для импорта общего файла (просто используйте фрагменты кода, которые говорят, что требуется). Я компилировал их с помощью ts, но они являются ванильным javascript и будут работать без предоставленного tsconfig. - person Griffork; 12.02.2021
comment
Я наградил вас наградой @griffork, чтобы оценить время, которое вы потратили на эти ответы. Однако ни один из них не решает мою проблему. Я не хочу иметь ни отдельный tsconfig для общего файла, ни отдельный preconfig. Еще раз спасибо за ваше время. :) - person Aidin; 17.02.2021