Typescript: Предоставьте способ добавить расширение файла «.js» в конец спецификаторов модуля.

Созданный на 16 июн. 2017  ·  273Комментарии  ·  Источник: microsoft/TypeScript

Чтобы использовать модули es6 в браузере, вам необходимо расширение файла .js. Однако вывод не добавляет его.

В тс:
import { ModalBackground } from './ModalBackground';
В выводе ES2015:
import { ModalBackground } from './ModalBackground';

В идеале я хотел бы, чтобы это было выведено
import { ModalBackground } from './ModalBackground.js';

Таким образом, я могу использовать вывод в Chrome 51.

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Webpack boilerplate</title>
  <script type="module" src="index.js"></script>
</head>
<body></body>
</html>

image

Связано с https://github.com/Microsoft/TypeScript/issues/13422

ES Modules Needs Proposal Suggestion

Самый полезный комментарий

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

Все 273 Комментарий

Это не просто связано с # 13422, это та же проблема. Но ответы были довольно негативными, несмотря на то, что я считаю это важным вопросом, поэтому надеюсь, что ваш вопрос будет лучше воспринят.

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

На данный момент TypeScript не перезаписывает пути. Это определенно раздражает, но в настоящее время вы можете самостоятельно добавить расширение .js .

@justinfagnani @rictic

Спасибо за совет, я напишу сценарий оболочки/узла, чтобы сделать это.

@DanielRosenwasser , имеет ли смысл собирать проблемы собственного модуля ES6 под лейблом?

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

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

Я не уверен, как обращаться с node_modules. Обычно webpack объединяет их в код через ts-loader, но, очевидно, браузер этого не понимает:

import { KeyCodes } from 'vanilla-typescript;
https://github.com/quantumjs/vanilla-typescript/blob/master/events/KeyCodes.ts#L3

Добавлять сюда расширение js бессмысленно.

Я предполагаю, что на сервере должно быть расширение пути с помощью машинописного текста или преобразователя URL-адресов.

Я ценю, что это довольно нишевый случай, но я думаю, что это был бы способ, которым TS мог бы проявить себя раньше в этой области. Может быть, это плагин к компилятору tsc?

Для тех, кто приходит к этому и хочет временное решение, я написал скрипт для добавления расширения файла js для операторов импорта:

"use strict";

const FileHound = require('filehound');
const fs = require('fs');
const path = require('path');

const files = FileHound.create()
  .paths(__dirname + '/browserLoading')
  .discard('node_modules')
  .ext('js')
  .find();


files.then((filePaths) => {

  filePaths.forEach((filepath) => {
    fs.readFile(filepath, 'utf8', (err, data) => {


      if (!data.match(/import .* from/g)) {
        return
      }
      let newData = data.replace(/(import .* from\s+['"])(.*)(?=['"])/g, '$1$2.js')
      if (err) throw err;

      console.log(`writing to ${filepath}`)
      fs.writeFile(filepath, newData, function (err) {
        if (err) {
          throw err;
        }
        console.log('complete');
      });
    })

  })
});

Я мог бы превратить это в инструмент cli ..

Комментарий @justinfagnani попал в самую точку.

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

когда ты пишешь

import { KeyCodes } from 'vanilla-typescript';

или в этом отношении

import { KeyCodes } from 'vanilla-javascript';

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

Если вы пишете приложение NodeJS, то алгоритм NodeJS Require будет пытаться разрешить различные разрешения, но, скорее всего, _не_ попытается разрешить его до 'vanilla-typescript.js' , потому что оно ссылается на абстрактное имя и по соглашению и конфигурации будет разрешено ( возможно, в результате различных попыток) до чего-то вроде '../../../node_modules/vanilla_typescript/index.js' .

Другие среды, такие как AMD, имеют различия в том, как они выполняют это разрешение, но у всех этих сред есть одна общая черта — некоторое понятие абстрактного спецификатора модуля.

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

Это может быть далеко, но, как вы обнаружите, нереально написать это (вежливо) доказательство реализации концепции, которое нам дали.

Кроме того, я не вижу, как TypeScript может помочь здесь, поскольку проблема зависит от среды.

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

Я в основном просто разглагольствую о том, что реализация модулей ES, которые были выпущены, чрезвычайно далека от адекватной.

Опять же, NodeJS, RequireJS AMD, Dojo AMD, Sea Package Manager, CommonJS, Browserify, Webpack, SystemJS — у всех свои способы работы, но все они обеспечивают абстрактное разрешение имен. Они должны обеспечить это, потому что это _фундаментально_.

Спасибо, что прочитали мою тираду.

Не уверен, какая версия TS добавила его, но теперь работает импорт, такой как « ./file.js' » (даже если файл на самом деле file.ts).
TypeScript отлично разрешает файл и выводит полный импорт .js в цель.
lit-html используйте его: https://github.com/PolymerLabs/lit-html/blob/master/src/lib/repeat.ts#L15

Это возможно с TS 2.0. Но такие инструменты, как webpack, не поддерживают его, поэтому, в конце концов, он бесполезен.

Это бесполезно, если вы используете ts-loader для источников (наиболее распространенный вариант использования).
По-прежнему можно связать цель (обычно папку «dist»), так как фактический файл js существует там и может быть найден в процессе разрешения.

Интересно, смогу ли я реализовать быстрое преобразование в ts-loader , которое удаляет расширения .js из целевого кода, позволяя выполнять сборку непосредственно из исходников.

Не стесняйтесь делать это, это было бы здорово. Несколько месяцев назад я разместил сообщение о проблеме с основными загрузчиками webpack ts, такими как ts-loader, и был довольно плохо принят...

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

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

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

До тех пор мы будем зависеть от таких инструментов, как SystemJS и Webpack.

Я создал крошечный преобразователь, который удаляет «.js» из операторов импорта/экспорта.
Я использовал защиту типа tsutils , поэтому yarn add tsutils --dev . (пакет обычно устанавливается в любом случае, если в вашем проекте есть tslint , так что дополнительная зависимость)

https://gist.github.com/AviVahl/40e031bd72c7264890f349020d04130a

Используя это, можно связать ts-файлы, которые содержат импорт из файлов, оканчивающихся на .js (используя webpack и ts-loader ), и по-прежнему транспилировать исходники в модули esm, которые могут загружаться в браузер (используя tsc ).

Вероятно, существует ограниченное количество вариантов использования, в которых это полезно.

РЕДАКТИРОВАТЬ: я обновил суть, чтобы работать и с экспортом. это наивно и не оптимизировано, но работает.

Есть какие-то движения по этому вопросу?

Этот вопрос расширения возвращает нас к самому началу TypeScript и к тому, почему понадобился параметр tsconfig.json и почему параметр module был добавлен к параметру compilerOptions .

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

  1. .js за .ts
  2. .jsx за .tsx

Здравствуйте, я приду так поздно, но хотел бы помочь. Мне трудно понять, в чем здесь проблема. Из примера OP это:

import { ModalBackground } from './ModalBackground';

Проблема в том, что мы не знаем, что такое './ModalBackground' ? Это может быть папка или что-то еще?

Если мы запустим tsc для всего проекта и будем знать, что ModalBackground.ts существует, то мы будем знать, что добавление расширения безопасно, не так ли?

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

Я не совсем уверен, является ли это проблемой, если целью вывода является ES2015, не так ли? Возможно, это относится к области возможностей браузера ES2015. Более того, @justinfagnani , разве мы не можем продвигать это как цель платформы, о которой стоит беспокоиться? (Возможно, нужно разветвить в отдельный поток).

Более того, @justinfagnani , разве мы не можем продвигать это как цель платформы, о которой стоит беспокоиться? (Возможно, нужно разветвить в отдельный поток).

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

Даже если мы в конечном итоге получим поддержку голых спецификаторов, невероятно маловероятно, что она будет в форме разрешения узла-модуля как есть. Таким образом, будет несоответствие между алгоритмом разрешения, используемым tsc для поиска файлов, и алгоритмом разрешения, используемым браузерами (и, возможно, даже собственной поддержкой модулей узла, если честно).

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

@justinfagnani их уже интерпретируют с противоречивым мнением. TS создает файл JS, на который не указывает созданный им код JS. ES6 ближе всего к официально правильному способу работы с JavaScript, поэтому, если код ES6, созданный TypesScript, неверен, это простая ошибка. Нет необходимости ждать каких-либо предложений и тому подобного, просто исправьте ошибку TypeScript. Но сегодня люди чувствуют, что если они не придираются к чему-то и не проходят через 10 слоев предложения, прежде чем действовать, то они действуют не интеллектуально. Дай мне перерыв.

@aluanhaddad Это правда, что многие проекты не выиграют, но есть некоторые проекты, которые не используют зависимости npm (или которые могут каким-то образом обрабатывать зависимости npm), поэтому эти проекты выиграют.

Это также очень полезно для библиотек TypeScript, которые скомпилированы в ES6. Сейчас эти библиотеки нельзя использовать в браузере, но если бы TypeScript выводил расширение .js , то они бы работали.

@justinfagnani Это еще не стандартизировано и не реализовано, но есть предложение заставить пакеты npm работать в браузере.

Карта имен пакетов может быть автоматически сгенерирована компилятором TypeScript или другим инструментом.

Итак, я снова пересматриваю это, был ли какой-нибудь хороший обходной путь, кроме моего скрипта узла?

Я использовал это решение:
https://github.com/Microsoft/TypeScript/issues/16577#issuecomment -343610106

Но я считаю, что если модуль не имеет расширения файла, но обслуживается с правильным типом MIME, это должно разрешиться.

Любое движение по этому поводу?

может https://github.com/Microsoft/TypeScript/pull/25073 может решить эту проблему?

@Kingwl Будете ли вы поддерживать некоторые другие расширения файлов? например .mjs .es .esm .

может и нет, это другая особенность

Как это вообще вещь? Компилятор машинописного текста _знает_, что целевой вывод представляет собой файл JS. Я просматривал эти темы в течение 15 минут и до сих пор не понимаю, почему в нем отсутствует расширение.

Судя по количеству ссылок на эту проблему, я предполагаю, что она движется в правильном направлении. У меня скоро будет еще одна попытка.

Как это вообще вещь? Компилятор машинописного текста _знает_, что целевой вывод представляет собой файл JS. Я просматривал эти темы в течение 15 минут и до сих пор не понимаю, почему в нем отсутствует расширение.

Существуют распространенные варианты использования, которые люди используют, когда отсутствие расширения позволяет создать более гибкую инфраструктуру. Узел требует хука и загрузчика веб-пакета — два таких случая.

Как это вообще вещь? Компилятор машинописного текста _знает_, что целевой вывод представляет собой файл JS. Я просматривал эти темы в течение 15 минут и до сих пор не понимаю, почему в нем отсутствует расширение.

Существуют распространенные варианты использования, которые люди используют, когда отсутствие расширения позволяет создать более гибкую инфраструктуру. Узел требует хука и загрузчика веб-пакета — два таких случая.

Ни один из модулей браузера не заботится о них.

Будет ли это просто убить команду машинописи, чтобы добавить флаг согласия для создания расширения .js? Мы _делаем_ знаем, что здесь делаем, иначе не было бы дюжины тем (как открытых, так и закрытых), в которых до сих пор собираются ответы и запутанные вопросы. Мы понимаем, что это не недостаток TS, но если TS здесь, чтобы решить наши проблемы с JS, добавьте эту проблему в список, пожалуйста.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ:

Да, я понимаю, что это может привести к тому, что множество людей будут публиковать здесь сообщения о том, что «вы сломали веб-пакет», но на самом деле, этим людям трудно. Это должно быть согласие.

Кстати, копаясь в исходном коде TypeScript, я вижу importModuleSpecifierEnding — можно ли это (ab) использовать, чтобы эмиттер использовал окончания .js ?

Может быть, смешать это предложение со схемой tsconfig? https://github.com/domenic/имя-пакета-карты

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

Любые обновления? Любые попытки решить эту проблему? У нас есть все основные браузеры, поддерживающие модули es по умолчанию, стандарт для которых требует наличия расширения. Я понимаю, что мы можем добавить его вручную, и tsc это поймет, но это не должно быть обязательным, почему это не может просто работать?
Извините за нытье, но эта тема уже очень старая и ничего еще не сделано...

Как это вообще вещь? Компилятор машинописного текста _знает_, что целевой вывод представляет собой файл JS. Я просматривал эти темы в течение 15 минут и до сих пор не понимаю, почему в нем отсутствует расширение.

Существуют распространенные варианты использования, которые люди используют, когда отсутствие расширения позволяет создать более гибкую инфраструктуру. Узел требует хука и загрузчика веб-пакета — два таких случая.

Тогда, возможно, компилятор Typescript мог бы принять возможность добавлять расширения или нет. Возможно, он мог бы даже принять набор регулярных выражений, чтобы добавить (или не добавить) расширение, например параметр включения (https://www.typescriptlang.org/docs/handbook/tsconfig-json.html).

Да, это уже было предложено как минимум один раз, почему бы не принять это во внимание? В TS уже есть несколько экспериментальных функций, которые могут измениться в будущем после реализации в браузере, но в TS уже есть флаги для этих нестабильных спецификаций. Почему бы просто не иметь даже экспериментальный флаг addImportsExtensions , где он просто делал бы module += '.js' , вот и все! Никакой навороченной логики, никаких дополнительных функций. Это может быть другая цель, если вы предпочитаете сохранить ее как отдельную цель. Более того, если вы примете что-либо из вышеперечисленного, я лично покопаюсь в коде tsc и сделаю для этого пиар, просто не хочу терять время, если его все равно не примут.

Вы можете просто использовать пользовательское преобразование для перезаписи импорта в испускаемом коде (добавляя '.js' или используя разрешенный путь импорта модуля).

Как написать преобразование TypeScript
ttypescript: оболочка для tsc , которая применяет преобразования во время компиляции.

Возможно, уже существует преобразование, которое делает то, что вам нужно.

Я знаю, что это возможно, я немного поиграл с API компилятора (хотя и не так много, как хотелось бы). Дело в том, что он добавляет в проект дополнительный инструмент, а у дополнительных инструментов есть дополнительные мейнтейнеры, которые могут или не могут реагировать на проблемы достаточно быстро, если вообще реагируют (часто не по их вине, у всех нас есть жизнь и работа). Небольшие проекты часто забрасываются, а выполнение всего самостоятельно просто перекладывает ответственность на нас, поэтому вместо того, чтобы заботиться о бизнес-коде, мы тратим время на инструменты.
Принимая во внимание вышеизложенное, многие проекты даже не рассматривают это как решение, а вместо этого добавляют дополнительные этапы сборки, такие как объединение и т. д., что добавляет дополнительные накладные расходы на конфигурацию и возвращает нас к дополнительным затратам на обслуживание.
Подводя итог: я предпочитаю тратить свое время на пиар официальному ТС, где от этого выиграю и я, и сообщество, чем тратить его на кастомное решение, от которого я со временем могу отказаться (по нехватке времени или многим другим причинам) ), или который не мог быть использован никем другим в мире.

@ajafff ​​Это может быть решением, но я думаю, что основная проблема заключается в следующем: транспилятор Typescript генерирует неверный исходный код в браузерах. Хорошо иметь преобразования, но я вижу в этом обходной путь. Интересно, должен ли я заботиться о деталях транспиляции и должен ли реализовать свое собственное преобразование или что-то, чем должен управлять компилятор.

Преобразования — действительно мощный инструмент, мы могли бы написать полностью новый транспайлер как преобразование, но я думаю, что это неправильный путь.

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

TypeScript имеет только один экспериментальный флаг, который был добавлен 3 года назад, и он был для предложения ECMAScript, которое больше не совместимо с текущим предложением.

транспилятор Typescript генерирует неправильный исходный код в браузерах

Я понимаю ваши ожидания, но, учитывая, что компилятор не переписывает пути, которые вы написали, я удивлен, что вы не считаете импорт вашего собственного кода «неправильным». 😉

Извините, @DanielRosenwasser , вы слышали о такой вещи, как npm? Люди размещают там свои пакеты, чтобы мы все могли их использовать. Я понимаю, что вы можете очень высоко ценить меня, но, к сожалению, я не являюсь автором подавляющего большинства из них, поэтому я не могу редактировать их, добавляя расширения.
Если бы в моих проектах использовался только мой код, я был бы более благодарен за то, что дает машинописный текст, поскольку он действительно моя правая рука в кодировании (помимо WebStorm). Однако я использую сторонние пакеты, как я думаю, большинство из нас, и они не обязательно содержат расширения. Некоторые проекты, такие как rxjs, буквально ждут с надеждой, что typescript предоставит способ добавления расширений, в противном случае им потребовалось бы изменить весь процесс сборки, поэтому мы снова тратим дополнительное время на инструменты, а не на продукт.
Теперь, пожалуйста, не могли бы вы просто ответить на 3 вопроса?

  1. Готова ли команда typescript выпустить эту функцию?
  2. Если да, согласились бы вы на PR?
  3. Если нет, то когда вы планируете это выпустить?

Если ответ на 1-й вопрос «нет», пожалуйста, закройте этот вопрос, официально заявив, что вы НЕ готовы выпускать эту функцию, не заставляйте других ждать, если она не появится.

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

TypeScript имеет только один экспериментальный флаг, который был добавлен 3 года назад, и он был для предложения ECMAScript, которое больше не совместимо с текущим предложением.

транспилятор Typescript генерирует неправильный исходный код в браузерах

Я понимаю ваши ожидания, но, учитывая, что компилятор не переписывает пути, которые вы написали, я удивлен, что вы не считаете импорт вашего собственного кода «неправильным». 😉

Это хороший момент @DanielRosenwasser , я просто посчитал свой собственный код правильным, потому что он кажется правильным при чтении спецификации Typescript (https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#11.3).

Я почти уверен, что вы читали спецификации ECMAScript. В спецификации не указано, должен ли модуль заканчиваться расширением или нет. В спецификациях импорт модулей разрешается с помощью алгоритма HostResolveImportedModule, но определение неоднозначно. Проблема не в спецификации ECMAScript. Проблема в том, что браузеры разрешают модули, как если бы [ModuleRequest], как определено в спецификациях, был путем к ресурсам.

Имея это в виду, просто перейдите на домашнюю страницу языка: https://www.typescriptlang.org/ .

В футере страницы вы можете прочитать следующие строки:

Начинается и заканчивается JavaScript

TypeScript исходит из того же синтаксиса и семантики, которые сегодня известны миллионам разработчиков JavaScript. Используйте существующий код JavaScript, включайте популярные библиотеки JavaScript и вызывайте код TypeScript из JavaScript.

TypeScript компилируется в чистый, простой код JavaScript, который запускается в любом браузере , на Node.js или в любом движке JavaScript, поддерживающем ECMAScript 3 (или новее).


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

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

Нет, мы не собираемся выпускать что-либо, связанное с этим, пока не будет хотя бы ясности в отношении таких вещей, как взаимодействие ES в Node, и разумной стратегии доставки транзитивных зависимостей, которые вы бы использовали в первую очередь из npm. Если бы вы не использовали TypeScript, у вас была бы та же проблема с управлением и разрешением зависимостей, поэтому для нас нет смысла придумывать что-то, что экосистема JS в целом могла бы развиваться независимо. Но даже если бы эти проблемы были решены, я не могу гарантировать, что мы внесем здесь какие-либо изменения.

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

Я думаю, что это толкование слишком буквально. var fs = require('fs') не работает при запуске в браузере, HTMLDivElement не определен в Node, а String.prototype.startsWith не работает в старых браузерах. Чтобы решить эту проблему, люди создали инструменты и библиотеки/полифиллы вне TypeScript, потому что они применимы к более широкой экосистеме JavaScript.

Так вы можете закрыть эту тему? Это блокировщик для других проектов, которые ждут , пока TS сделает это, или объявят, что вы этого не делаете. Если вы не можете просто добавить простой флаг, закройте эту проблему и сообщите другим о ваших решениях.

@DanielRosenwasser Спасибо за быстрый ответ, я очень ценю это. Я думаю, это мудрый выбор.

Я думаю, что это толкование слишком буквально. var fs = require('fs') не работает при запуске в браузере, HTMLDivElement не определен в Node, а String.prototype.startsWith не работает в старых браузерах. Чтобы решить эту проблему, люди создали инструменты и библиотеки/полифиллы вне TypeScript, потому что они применимы к более широкой экосистеме JavaScript.

Конечно, да, но что еще может подумать тот, кто ничего не знает о машинописном тексте? То, что моя интерпретация слишком буквальна, так же верно, как и то, что этот текст может «запутать» любого, кто ничего не знает о Typescript 😉.

Возможно, вы могли бы обновить свои документы (https://www.typescriptlang.org/docs/handbook/modules.html) , чтобы отразить фактическое поведение.

@DanielRosenwasser еще раз спасибо за ваш ответ. Я уже год жду чего-то подобного.

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

Для таких людей, как я, которые ищут решение для использования модулей ES и TypeScript в браузере сегодня, я нашел https://github.com/guybedford/es-module-shims. Он действует как своего рода полифилл для карт имен пакетов, пока мы ждем завершения спецификации и реализации в браузере. Он решает проблему @QuantumInformation , связанную с желанием не использовать какие-либо инструменты сборки (и мою проблему), при создании простого веб-приложения в TypeScript (кроме компилятора TS).

import 'knockout'

export class MyViewModel {
    greeting: KnockoutObservable<string>
    target: KnockoutObservable<string>
    constructor() {
        this.greeting = ko.observable('hello')
        this.target = ko.observable('world')
    }
}
<!DOCTYPE html>


md5-f28d4b503a1603c40bfeb342f341bfbe


<main>
    <span data-bind='text: `${greeting()} ${target()}`'></span>
    <script type='module-shim'>
        import 'knockout'
        import { MyViewModel } from 'index'
        ko.applyBindings(new MyViewModel())
    </script>
</main>

Теоретически, как только карты имен пакетов будут поддерживаться браузерами, вы можете просто найти/заменить type='module-shim' на type='module' в своих HTML-файлах и изменить сценарий packagemap на то, что в конечном итоге будет завершено для включения packagemap в спец.

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

@weswigham , это может быть очень проблематично, потому что tsc (и классическое разрешение модуля узла) будет знать, что ./foo и ./foo.js относятся к одному и тому же файлу, но браузеры будут обрабатывать их по-разному, даже если веб-сервер перенаправляет. Вы должны быть уверены, что ссылаетесь на файл точно таким же образом при каждом импорте.

Кстати, эта проблема не мешает сегодня использовать модули, сгенерированные TypeScript, в браузерах. Просто всегда импортируйте файлы с расширением .js . tsc делает все правильно и разрешает типы из файла .ts , и вы получаете совместимость с браузером.

@weswigham Имейте в виду, что бывают ситуации, когда вы обслуживаете файлы, не имея доступа к веб-серверу. GitHub Pages, IPFS, S3 и т. д. С появлением фреймворков одностраничных приложений становится все более и более распространенным использование «бессерверного» (где безсерверный здесь означает отсутствие сервера, которым вы управляете/настраиваете обслуживание своих ресурсов), поэтому вы нельзя полагаться на фильтры на стороне сервера для обслуживания apple.js при запросе на apple .

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

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

Просто всегда импортируйте файлы с расширением .js

Да, это тоже хорошо работает.

@QuantumInformation Используется ли ваш фрагмент здесь для открытого использования? Могу ли я использовать его в проекте? 😃

@distante да, ты можешь использовать это

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

  "jest": {
    ...
    "moduleNameMapper": {
      "(.*)\\.js": "$1"
    }
  }

Привет @MrAntix ,

Я думаю, что jest — это библиотека, которая должна адаптироваться к TypeScript, а не наоборот.

У меня есть другой сайт, с которым я не хочу использовать инструмент сборки. Это лучшее, что у нас есть:

https://github.com/microsoft/TypeScript/issues/16577#issuecomment-452312753

В качестве обходного пути вы можете просто сделать это так (даже если это файл ts, а не js) 😢

Screenshot 2019-06-05 at 22 47 49

Если кто хочет попробовать:
https://github.com/QuantumInformation/веб-ген-бот

Однако я не могу заставить отладку исходного кода работать с текущим tsconfig, сообщу.

В конце концов я вернулся к веб-пакету, node_modules был убийцей при попытке уйти от инструментов сборки в браузере.

Это не только Jest — если вы используете tsc для компиляции TypeScript перед публикацией, любой JS-модуль, импортирующий полученный пакет, сломается из-за различий в разрешении модулей.

Обсуждение здесь, кажется, немного раздвоилось на два связанных, но в конечном итоге отдельных вопроса:

  • Typescript должен генерировать файлы, которые могут быть изначально загружены в браузере.
  • Typescript должен решить тот факт, что пути модулей узлов не всегда являются допустимыми URL-адресами.

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

Однако первая проблема — это то, что Typescript может решить и должен расставить приоритеты, поскольку он является основным блокировщиком для большинства людей, желающих использовать Typescript для создания веб-приложений, ориентированных на современные браузеры.

На мой взгляд, проблема сводится к следующему:

Если при запуске tsc создается один файл с расширением .js , а затем другой файл, который импортирует первый файл .js , нет никакой двусмысленности в отношении того, какое расширение использовать, и должно быть возможность включить расширение.

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

Что касается первого варианта, я думаю, что аргумент командной строки был бы лучшим, и по умолчанию он был бы отключен. Я говорю это, потому что, если я использую веб-пакет, я не хочу, чтобы .js добавлялся к импорту, поскольку веб-пакет заботится о связывании модулей.

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

Я говорю это, потому что, если я использую веб-пакет, я не хочу, чтобы .js добавлялся к импорту, поскольку веб-пакет заботится о связывании модулей.

Однако Webpack прекрасно обрабатывает расширение .js , так что разницы нет.

На самом деле иногда необходимо использовать .js с Webpack (в ситуациях, когда есть несколько файлов с одинаковым именем, но разными расширениями).

Не могли бы вы подробнее объяснить, почему вы не хотите импортировать .js с помощью Webpack?

Когда я говорю I don't want , я имею в виду, что мне это не нужно для моих вариантов использования.

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

Установка для импорта значения .js приводит к тому, что ts-node перестает правильно работать с файлом. Это связано с тем, что ts-node компилирует только один файл за раз, и если содержимое выпущенного файла заканчивается require('./foo.js') , тогда, когда nodejs обрабатывает этот файл, он попытается загрузить ./foo.js , которого не существует. в любом месте на диске и, таким образом, это не удастся. С другой стороны, когда код требует ( ./foo ), будет вызван обработчик ts-node, после чего он сможет скомпилировать ./foo.ts в JS и вернуть его.

Если TypeScript выдает расширения .js во всех случаях, ts-node столкнется с той же проблемой. Однако, если есть возможность переключать автоматическое добавление расширений или нет, то ts-node может отключить эту опцию компилятора, что позволит текущей системе продолжать работать.

Поскольку Node.js --experimental-modules требует обязательных расширений файлов, API для этого является простым и не требует анализа зависимостей — такая опция, как --jsext , может переписать любое расширение .ts на .js Расширение .ts , например import 'npmpkg.ts' . Этот случай крайне редок, но чтобы всесторонне обработать его в разрешении, правило может состоять в том, чтобы сделать исключение для _bare specifiers_ в соответствии со строками - если голый спецификатор (не URL-адрес или относительный путь) является допустимым именем пакета npm ( соответствие /^(@[-_\.a-zA-Z\d]+\/)?[-_\.a-zA-Z\d]+$/ из https://github.com/npm/validate-npm-package-name), затем игнорируйте расширения .ts при переписывании.

Я создал преобразователь компилятора TypeScript, который добавит расширение файла .js к любому относительному пути импорта. Это означает, что если в вашем файле .ts есть import { Foo } from './foo' , он выдаст import { Foo } from './foo.js' . Он доступен на NPM, а инструкции по его использованию можно найти в файле readme проекта.

https://github.com/Zoltu/typescript-transformer-append-js-extension

Если что-то подобное должно быть интегрировано в компилятор TypeScript (как вариант компилятора), вероятно, следует разумнее решить, когда добавлять расширение .js , а когда нет. Прямо сейчас он ищет любой путь, начинающийся с ./ или ../ и не имеющий . где-либо еще в пути. Это означает, что он не будет работать правильно в ряде крайних случаев, хотя я сомневаюсь, столкнется ли кто-нибудь _фактически_ с такими крайними случаями или нет.

@MicahZoltu приятно видеть пользовательские решения для этого. Я думаю, что очень важно, чтобы мысленная модель всегда включала расширения файлов , так что параметр расширения TypeScript мог стать _превратить расширения .ts в расширения .js при компиляции_. Это позволяет избежать крайних случаев разрешения, оставляя только случай имен пакетов npm, которые заканчиваются на «.ts», что можно обработать, как я обсуждал в своем предыдущем комментарии.

@guybedford Включение расширения $# .js .ts делает его невозможным для выполнения в ts-узле. Решение проблемы в ts-node далеко не тривиально из-за того, как NodeJS выполняет разрешение файлов. Это означает, что если вы опубликуете библиотеку с жестко запрограммированными расширениями .js , эта библиотека не будет работать ни для кого, использующего ts-node. См. обсуждение этого вопроса на https://github.com/TypeStrong/ts-node/issues/783.

@MicahZoltu Я имею в виду включение расширения $# .ts .ts .

@guybedford Включение расширения .js в файл .ts делает файл невозможным для выполнения в ts-узле.

Это еще одна причина, по которой автоматическое выполнение TypeScript в узле и браузерах — плохая идея.

@MicahZoltu Я имею в виду включение расширения .ts в файл .ts.

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

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

Это означает, что если вы импортируете файл, скомпилированный с текущим проектом, вы используете .ts, а если вы перемещаете файл в другой проект, вам нужно изменить импорт, чтобы использовать .js.

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

Это также означает, что выход не работает в стандартных условиях без трансформатора.

В то время как преобразователь может помочь нам изучить это, --ts-to-js или аналогичный флаг/параметр компилятора очень необходим для решения этой проблемы.

@guybedford Вы убедили меня, что добавление .ts было правильным решением для плагина. Однако при попытке реализовать его я узнал, что TypeScript на самом деле не позволяет этого!

// foo.ts
export function foo() { console.log('foo') }
// bar.ts
import { foo } from './foo.ts' // Error: An import path cannot end with a '.ts' extension. Consider importing './foo' instead
foo()

Здравствуйте, что насчет этого?


Вход:

// src/lib.js.ts
export const result = 42;
// src/index.js.ts
import { result } from "./lib.js";

console.log(result);

выход:

// build/lib.js
export const result = 42;
// build/index.js
import { result } from "./lib.js";

console.log(result);

выпуск №30076

Единственное расширение .ts в файле TypeScript кажется мне наиболее подходящим. Часто вы не знаете до момента компиляции, что является целью. Например, во многих моих библиотечных проектах у меня есть несколько файлов tsconfig.json , предназначенных для разных сред, например, для современных браузеров, которые должны создавать файлы .js и сопоставлять пути импорта с .js , или ориентируясь на современный Node, который должен выдавать файлы .mjs и сопоставлять пути импорта с .mjs .

@MicahZoltu , что импорт файлов, оканчивающихся на .ts , является ошибкой, на самом деле, возможно, в нашу пользу. Потому что это означает, что расширение от .ts до .js , перезаписываемое при компиляции, может быть добавлено всякий раз, когда используются расширения .ts без флага :)

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

//cc @DanielRosenwasser

Эта тема уже очень длинная, поэтому, возможно, кто-то уже говорил это, поэтому рискую повторить то, что уже было сказано:

TypeScript должен позволять разработчикам указывать расширения в import s, потому что это действительный JavaScript. И речь идет не только о расширении JS/TS! В ESM любое расширение допустимо, если указан правильный тип MIME.

import actuallyCode from './lookLikeAnImage.png';

… должно быть действительным, пока сервер обслуживает действительный JavaScript в этом файле и устанавливает правильный тип MIME. Это идет дальше, поскольку то же самое может быть верно для TS! Файл TS может быть просто исходным кодом JS с типом JS MIME и, таким образом, допустимым путем для импорта модуля ESM.

IMO TypeScript должен рассматривать только импорт без расширения (как он хочет, чтобы вы были сегодня) и оставлять только те, без ошибок, предупреждений и т. д. В противном случае он отклоняет действительный код JavaScript, что довольно неудачно для чего-то, что претендует на то, чтобы быть надмножеством JS.

Извините, если это не то место, чтобы поднять этот вопрос, я видел несколько других вопросов: # 18971, # 16640, # 16640, но вопросы по этой теме, похоже, закрываются слева и справа, поэтому я предполагаю, что это «основной» так как ему разрешили оставаться открытым.

Игра с NodeJS v12.7.0

salathiel@salathiel-genese-pc:~/${PATH_TO_PROJECT}$ node --experimental-modules dist/spec/src/ioc
(node:15907) ExperimentalWarning: The ESM module loader is experimental.
internal/modules/esm/default_resolve.js:59
  let url = moduleWrapResolve(specifier, parentURL);
            ^

Error: Cannot find module '${PROJECT_ROOT}/dist/spec/src/ioc' imported from ${PROJECT_ROOT}/
    at Loader.resolve [as _resolve] (internal/modules/esm/default_resolve.js:59:13)
    at Loader.resolve (internal/modules/esm/loader.js:73:33)
    at Loader.getModuleJob (internal/modules/esm/loader.js:149:40)
    at Loader.import (internal/modules/esm/loader.js:133:28)
    at internal/modules/cjs/loader.js:830:27
    at processTicksAndRejections (internal/process/task_queues.js:85:5) {
  code: 'ERR_MODULE_NOT_FOUND'
}
salathiel@salathiel-genese-pc:~/${PATH_TO_PROJECT}$ node --experimental-modules dist/spec/src/ioc.js
(node:16155) ExperimentalWarning: The ESM module loader is experimental.
internal/modules/esm/default_resolve.js:59
  let url = moduleWrapResolve(specifier, parentURL);
            ^

Error: Cannot find module '${PROJECT_ROOT}/dist/spec/src/observe' imported from ${PROJECT_ROOT}/dist/spec/src/ioc.js
    at Loader.resolve [as _resolve] (internal/modules/esm/default_resolve.js:59:13)
    at Loader.resolve (internal/modules/esm/loader.js:73:33)
    at Loader.getModuleJob (internal/modules/esm/loader.js:149:40)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:43:40)
    at link (internal/modules/esm/module_job.js:42:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Теперь я не уверен, почему это раздражает...

На данный момент TypeScript не перезаписывает пути. Это определенно раздражает, но в настоящее время вы можете самостоятельно добавить расширение .js .

@DanielRosenwasser https://github.com/microsoft/TypeScript/issues/16577#issuecomment -309169829

Как насчет реализации за опцией? Например, --rewrite-paths ( rewritePaths: true )?

@ viT-1 Вот временное решение: https://github.com/microsoft/TypeScript/issues/16577#issuecomment -507504210

@MicahZoltu Я просто решаю свой вариант использования с помощью объединения SystemJS (опция tsconfig outFile)

Я не читал все комментарии, которые люди написали об этом, но я не знаю, почему я должен писать .js тысячу раз. Я хочу, чтобы компьютер сделал это за меня.

@richardkazuomiller Мы все делаем, но @DanielRosenwasser заявил в https://github.com/microsoft/TypeScript/issues/16577#issuecomment -448747209, что они пока не хотят этого делать (я удивлен, что этот вопрос все еще обманчиво открыт) в течение столь долгого времени после вышеуказанного заявления). Если вы хотите, чтобы компьютер сделал это за вас, рассмотрите возможность использования сборщика или какого-либо стороннего инструмента для обработки перезаписей путей импорта.

Кто хочет, чтобы я закрыл эту тему?

Пожалуйста, не закрывайте, я все еще жду, как команда TypeScript отреагирует на то, как они собираются подходить к импорту ESM, который позволяет использовать любое расширение и вместо этого полагаться на тип MIME. На данный момент это возможно в JavaScript, но не в TypeScript. (Пожалуйста, смотрите мой предыдущий комментарий для деталей.)

@TomasHubelbauer Вот почему я предложил флаг в файле конфигурации, он может указывать на то, что все импорты без расширений должны иметь добавленное расширение .js (или любое другое настроенное). Это будет согласие, поэтому значение по умолчанию может быть ложным, заставляя существующие проекты или проекты с другими потребностями работать так, как есть.

Как было сказано ранее:

Не уверен, какая версия TS добавила его, но теперь работает импорт, такой как « ./file.js' » (даже если файл на самом деле file.ts).
TypeScript отлично разрешает файл и выводит полный импорт .js в цель.

Это имеет смысл, потому что любой допустимый JavaScript является допустимым TypeScript. Поскольку вы можете сделать:

import foo from './bar.js'

... в JS вы сможете сделать это и в TS. Если вы сделаете это, вы решите проблему использования нативных модулей ES6, потому что у вас правильные расширения.


Не будем также забывать, что когда браузер видит импорт для ./foo/bar , он фактически делает запрос на него. Тот факт, что ничего не было подано, был связан с сервером. Вы можете настроить его таким образом, чтобы запросы на /foo/bar удовлетворялись /foo/bar.js . Не сказать, что это хорошее решение или даже хорошая идея , но технически это сработает.

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

Это решило бы подавляющее большинство случаев. Захочет ли команда TypeScript рассмотреть PR для этой опции конфигурации?

NodeJS теперь _по умолчанию_ ведет себя так же, как браузеры, когда дело доходит до разрешения модуля относительного пути. Он больше не будет выводить расширение .js по умолчанию. Это означает, что текущее поведение TSC приводит к генерации кода JS, который недействителен во всех контекстах времени выполнения. Похоже, что теперь эту проблему следует решить, поскольку есть ясность в поведении браузера и NodeJS для ESM.

https://nodejs.org/api/esm.html#esm_customizing_esm_specifier_resolution_algorithm

Новому преобразователю для esm нужен новый режим разрешения — moduleResolution: node самом деле является просто преобразователем cjs для того, что я теперь могу назвать «старыми версиями узла». Если вы собираетесь использовать новый преобразователь esm, нам потребуется новый режим разрешения для более подходящего соответствия. Тем более, что нода по-прежнему полностью поддерживает старый резолвер во всех существующих конфигурациях. (Обратите внимание: сделать такой новый преобразователь _нашим по умолчанию_ будет сложно)

Хоть! Хотя есть _несогласие_ по этому поводу и _некоторые люди решат изложить мнение как факт_, все еще есть флаг --es-module-specifier-resolution=node , который возвращает ожидаемое поведение расширения и все еще может стать значением по умолчанию - как говорится в документах, несмотря на то, что он не помечен. , модули es в узле _по-прежнему являются экспериментальными_.

Кроме того, в качестве напоминания для исходного запроса: мы не перезаписываем импорт. Всегда. Вообще. Спецификатор на входе === спецификатор на выходе. Спецификаторы описывают структурный замысел, и мы не ставим перед собой цель неявно отображать одну намеченную структуру на другую. Вы также можете подумать об этом так: если бы вы написали const varFoo = "./Foo"; import(varFoo) , мы бы каким-то образом добавили туда расширение, если это необходимо? Нет — это смешно — чтобы обрабатывать все формы динамического ввода, нам нужно было бы обернуть динамический импорт во время выполнения, и внезапно мы стали собственным загрузчиком модулей, слоем поверх встроенного загрузчика платформы. Вместо этого мы бы предоставили режим распознавателя, который соответствующим образом выдает ошибку, когда вы пропускаете расширение (для которого, конечно же, вы, несомненно, уже можете найти правила lint).

Если вы нашли эту ветку и _действительно_ хотите_, чтобы ваши источники ввода не имели расширений, и вам _действительно_нужно_, чтобы ваш вывод по-прежнему работал с ним при нацеливании модулей (node ​​es), вы должны оставить отзыв на https://github.com/ nodejs/modules/issues/323 с вашим обоснованием, чтобы он мог работать таким образом на самой целевой платформе, поскольку в конечном итоге это то, на что мы опираемся.

внезапно мы стали собственными загрузчиками модулей

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

NodeJS теперь по умолчанию ведет себя так же, как и браузеры, когда речь идет о разрешении модуля относительного пути. Он больше не будет выводить расширение .js по умолчанию. Это означает, что текущее поведение TSC приводит к генерации кода JS, который недействителен во всех контекстах времени выполнения.

Разве это не еще одна причина просто использовать расширения файлов .js в спецификаторах, которые уже поддерживает TypeScript? Это решает все, кроме того, что было бы здорово, если бы tsc ошибся при импорте без расширения.

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

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

Разве tsc не должен быть функциональным загрузчиком модулей, несмотря ни на что?

Не во время выполнения. tsc должен понимать, как выбранная среда выполнения будет разрешать спецификаторы и реализовывать это во время сборки, но среда выполнения полностью зависит от среды.

Вы также можете подумать об этом так: если вы написали const varFoo = "./Foo"; import(varFoo) мы бы как-то добавили туда расширение, если нужно?

@weswigham Это сильный аргумент в отношении динамического импорта, но я не думаю, что вы можете сделать это со статическим импортом? Я могу оценить аргумент о том, что стратегия должна быть одинаковой для обоих, но я думаю, что стоит упомянуть, что статический импорт выполняет совсем другую роль, чем динамический импорт, и я не думаю, что совершенно _неразумно_ иметь другую стратегию для статического перезапись импорта и перезапись динамического импорта.

Разве это не еще одна причина просто использовать расширения файлов .js в спецификаторах, которые уже поддерживает TypeScript? Это решает все, кроме того, что было бы здорово, если бы tsc выдавал ошибку при импорте без расширения.

@justinfagnani С этим есть две проблемы:

  1. Среда выполнения, которая изначально выполняет TS (например, TS-Node), не будет работать, если вы укажете расширения .js для импорта.
  2. Вы лжете компилятору (IMO), если включаете расширения .js в свой импорт.

Что касается (2), если у меня есть два файла TS a.ts и b.ts , а a.ts делает import ... from './b.js' , я говорю компилятору: «У меня есть родственный файл с именем b.js . Это утверждение неверно. Что еще хуже, если у вас есть и .b.ts , и b.js (которые на самом деле могут не быть производными друг друга), это теперь становится неясным, на какой из них вы ссылаетесь, даже если вы явно включили расширение_.

Я придерживаюсь мнения, что пользователь должен сообщить компилятору, чего он на самом деле хочет (как пользователь), а именно «импортировать любой файл с именем X и любым расширением» (в случае import ... from './foo' ) или «импортировать именно этот файл» (в случае import ... from './foo.ext' ). Если компилятор обнаруживает, что вы импортируете файл TS, и компилятор продолжает создавать файл .js , то я считаю, что компилятор должен обновить импорт, чтобы правильно импортировать соответствующий файл. Это может означать изменение .ts на .js в операторе импорта.

@justinfagnani С этим есть две проблемы:

  1. Среда выполнения, которая изначально выполняет TS (например, TS-Node), не будет работать, если вы укажете расширения .js для импорта.

Это ошибка в TS-Node. Это не соответствует поведению tsc .

  1. Вы лжете компилятору (IMO), если включаете расширения .js в свой импорт.

На самом деле все наоборот - вы говорите правду о том, что на самом деле будет импортировано. Вы будете импортировать не файл .ts , а файл .js . Также не должно быть видимой разницы между парой .d.ts / .js и файлом .ts . Они взаимозаменяемы. Единственный правильный способ добиться этого — импортировать файл .js — таким, каким будет файл .ts после компиляции.

@justinfagnani

Также не должно быть видимой разницы между парой .d.ts/.js и файлом .ts.

Это не всегда правда. Вы можете настроить свой сервер для обслуживания всех JS, TS и DTS с типом JS MIME, а затем импортировать их все отдельно в JavaScript, и среда выполнения будет выполнять их все как JS. ESM вообще не заботится о расширениях.

Вот почему я думаю, что пользователи TS должны быть вынуждены включать расширение .ts , а расширение без расширения было бы ошибкой, если только фактически не импортируется файл без расширения или это имя. И TS переписал бы импорт в .js на выходе. И если бы файл JS существовал (а не созданный TS), это также было бы ошибкой.

Это ошибка в TS-Node. Это не соответствует поведению tsc.

Это ограничение загрузчика NodeJS, а не ошибка в TS-Node: https://github.com/TypeStrong/ts-node/issues/783#issuecomment -507437929

Это не всегда правда. Вы можете настроить свой сервер для обслуживания всех JS, TS и DTS с типом JS MIME, а затем импортировать их все отдельно в JavaScript, и среда выполнения будет выполнять их все как JS. ESM вообще не заботится о расширениях.

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

Я хочу сказать, что если у вас уже есть пара .js / .d.ts , скажем, из стороннего пакета, и вы импортируете файл .js , tsc будет просмотрите файл .d.ts и загрузите типы. т. е. пара .js / .d.ts _действует_ как файл .ts , и так оно и должно быть, поскольку именно так вы можете прозрачно портировать с JavaScript на TypeScript без изменения импорт файлов, которые переносятся.

Это ошибка в TS-Node. Это не соответствует поведению tsc.

Это ограничение загрузчика NodeJS, а не ошибка в TS-Node: TypeStrong/ts-node#783 (комментарий)

Это все еще ошибка, что TS-Node отклоняется от поведения tsc . Это приводит к тому, что файлы .ts не работают как в tsc , так и в TS-Node, и я настоятельно рекомендую tsc установить стандарты, которым должен следовать TS-Node. .

Я хочу сказать, что если у вас уже есть пара .js/.d.ts, скажем, из стороннего пакета, и вы импортируете файл .js, tsc увидит файл .d.ts и загрузит типы. т. е. пара .js/.d.ts действует как файл .ts, и так и должно быть, поскольку именно так вы можете прозрачно переносить с JavaScript на TypeScript, не изменяя импорт переносимых файлов.

Если вы загружаете внешний _package_, вам понадобится какой-то загрузчик пакетов во время выполнения (например, именованные карты импорта в браузере), который выполняет сопоставление именованного модуля с файлом точки входа. Тем не менее, я думаю, что ваша точка зрения в целом остается в силе в случае, когда у вас есть относительная пара .js/.d.ts. Я не знаю, следует ли в этом случае делать import ... from './foo.d.ts' или import ... from './foo.js' .

Файл .d.ts , по сути, является заголовком, описывающим структуру, которая не содержит информации о том, из какого расширения он отображается (предполагается, что обычно у вас не должно быть нескольких файлов с одним и тем же именем, но с разными расширениями в одном и том же месте, и мы ошибаемся при сборке, если вы это сделаете) - даже сегодня связанный «источник» среды выполнения может быть .js или .jsx (с использованием jsx: preserve ). Вы не могли бы в целом заменить ссылку .d.ts на .js в импорте во время отправки и предположить, что это работает...

Важно именно то, что tsc не слишком самоуверенно относится к более широкому
строить и разрешать предположения.

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

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

В среду, 27 ноября 2019 г., в 16:48 Уэсли Уигхэм, [email protected]
написал:

Файл .d.ts по существу является заголовком, описывающим структуру, которая содержит
нет информации о том, из какого расширения он отображается (предполагается, что
как правило, у вас не должно быть нескольких файлов с одинаковым именем, но
разные расширения в одном и том же месте) - даже сегодня связанные
«Источник» среды выполнения может быть .js или .jsx (с использованием jsx: сохранить). Ты мог бы
в целом не заменять ссылку .d.ts на .js при импорте во время отправки
и предположим, что это работает...


Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/microsoft/TypeScript/issues/16577?email_source=notifications&email_token=AAESFSQS2DQ23RR5KN3RTZ3QV3TLXA5CNFSM4DPRQTY2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEFK2TPA#issuecomment
или отписаться
https://github.com/notifications/unsubscribe-auth/AAESFSUAP2YO23ZFHCOWVQLQV3TLXANCNFSM4DPRQTYQ
.

Не уверен, как справиться с этим сценарием, но имел сомнения, связанные с тем же самым.

У меня есть такая карта импорта в моем html-файле:

<script type="importmap-shim">
      {
        "imports": {
          "@root/":"../../../",
         }
      }
</script>

И у меня есть файл ts , в который я импортирую такой файл:

import '@root/components/page-main/page-main.js';

Теперь эта настройка хорошо работает в браузере. Но как я смогу перемещаться/использовать его в VSCode? Я имею в виду, что я хочу щелкнуть ctrl+клик по импорту и перейти к файлу, получить автозаполнение, ввести def и т. д.

Кроме того, учитывая, что tsc не переписывает расширения импорта из .ts в .js , есть ли какой-либо другой рекомендуемый инструмент/пакет, который я могу использовать, чтобы сделать то же самое во время сборки? Спасибо.

(Я использую https://github.com/guybedford/es-module-shims для модулей ES и импорта карт)

Но как я смогу перемещаться/использовать его в VSCode?

Найдите параметр компилятора paths .

Кроме того, учитывая, что tsc не переписывает расширения импорта из .ts в .js , есть ли какой-либо другой рекомендуемый инструмент/пакет, который я могу использовать, чтобы сделать то же самое во время сборки? Спасибо.

Просто используйте .js , и он будет работать нормально, даже если вы ссылаетесь на файл .ts во время сборки.

@tvvignesh https://github.com/Zoltu/typescript-transformer-append-js-extension/ для перезаписи импорта без расширений в .js во время компиляции. Я лично не являюсь поклонником «просто поместите .js в свои файлы TS», потому что ваш код не будет работать в ts-узле, если вы это сделаете. Если вам не нужно запускать свой код в ts-node, то сработает использование .js.

Но как я смогу перемещаться/использовать его в VSCode?

Найдите параметр компилятора paths .

Кроме того, учитывая, что tsc не переписывает расширения импорта из .ts в .js , есть ли какой-либо другой рекомендуемый инструмент/пакет, который я могу использовать, чтобы сделать то же самое во время сборки? Спасибо.

Просто используйте .js , и он будет работать нормально, даже если вы ссылаетесь на файл .ts во время сборки.

Спасибо за ваш быстрый ответ. Я уже установил параметр путей в tsconfig.json, но до сих пор не могу перемещаться с помощью Ctrl+щелчок.

Это моя опция путей в tsconfig.json

"paths": {
            "*": ["www/node_modules/*"],
            "@modules/*": ["www/node_modules/*"],
            "@root/*": ["www/*"]
        }

Просто используйте .js , и он будет работать нормально, даже если вы ссылаетесь на файл .ts во время сборки.

Это совершенно непрактично, когда есть тысячи импортов.

Проблема с «просто используйте .js » заключается в том, что если TypeScript выдает файлы .mjs , ваша программа не работает. Это означает, что вы окажетесь в ситуации, когда вы пишете TypeScript, который либо работает в браузере, либо работает в NodeJS. Вы больше не можете писать TypeScript, который работает в обоих случаях.

Я считаю, что аргумент здесь таков: «Это не вина TypeScript, это расхождение браузера и NodeJS».

Node 13.2 прекрасно поддерживает расширения .js.

@justinfagnani Для модулей ES? Я думал, что NodeJS будет загружать модули ES только в том случае, если они имеют расширение .mjs , иначе файлы обрабатываются как CommonJS?

Я чувствую, что вся эта ветка немного ошибочна. Явное написание расширения файла решило бы всю эту проблему. Если вы импортируете файл JavaScript, напишите расширение .js. Если вы импортируете файл TypeScript, напишите расширение .ts. Это разрешено в стандарте и компилятор TypeScript все это понимает одинаково хорошо. Единственная проблема заключается в том, что компилятор заявляет, что расширения .ts являются ошибками. Это не влияет на чистую транспиляцию, а является только ошибкой типа. TypeScript должен исправить это, так как очевидно, что расширение файла .ts допустимо, поскольку мы пишем в TypeScript. Чтобы обойти эту проблему, Deno.js имеет расширение VS Code: https://marketplace.visualstudio.com/items?itemName=justjavac.vscode-deno .

С появлением WebAssembly веб-приложения начнут импортировать все больше и больше типов файлов. Становится все более важным явно указать, импортируете ли вы файл .wasm, .js, .ts, .rs, .c и т. д.

Кто-нибудь действительно использовал сценарий, который я написал?

https://github.com/microsoft/TypeScript/issues/16577#issuecomment-310426634

есть ли отзывы, если да?

@QuantumInformation Я не использовал ваш скрипт, но плагин преобразователя TypeScript, который я написал, делает в основном то же самое. 😊 https://github.com/Zoltu/typescript-transformer-append-js-extension/

Прежде всего, я не собираюсь снова пытаться убедить машинописный текст реализовать это, я понимаю, вы этого не сделаете.
Однако я читаю комментарии и задаюсь вопросом: все те люди, которые говорят, что добавление .js к путям решит все это - вы действительно не используете сторонние пакеты? Как мне добавить расширения к моему импорту, исправляя то, что находится в node_modules?

@MicahZoltu о, хорошенький

Что ты имеешь в виду? Вы должны явно написать расширение файла, который вы импортируете из node_modules, если используете путь. Но разве это в любом случае не будет голым импортом?

Если вы укажете относительный путь, он не будет голым. Однако я говорю о внутреннем импорте пакета, который я импортирую, посмотрите, например, на rxjs.

@Draccoz Я считаю, что смысл в том, что если кто-то напишет TypeScript как import { ... } from './foo' , а затем опубликует это как пакет NPM, пользователь не сможет использовать эту библиотеку непосредственно в браузере, даже если она нацелена на модули ES. Я полагаю, что аргумент Microsoft здесь заключается в том, что пакет неверен, если он распространяет такой код, ожидая, что он будет работать в браузере.

Вы бы написали расширение файла, который существует в node_modules. import * as stuff from 'rxjs/path/to/file.js'; , если это файл JavaScript, и import * as stuff from 'rxjs/path/to/file.ts'; , если они распространяли файл TypeScript. Это работает прямо сейчас, если я не ошибаюсь

@lastmjs Да, но что, если rxjs/path/to/file.ts содержит import foo from './bar' ? Вы не можете изменить это, так как вы не можете изменить файл, так как это сторонняя библиотека.

Вот почему мы должны настаивать на использовании явных расширений везде, но да, я понимаю вашу точку зрения. Мой инструмент (https://github.com/lastmjs/zwitterion) делает это переписывание в качестве временного решения для тех файлов, которые не имеют расширений.

Да, моя точка зрения была именно такой: простое добавление расширений не исправит сторонние библиотеки, которые мы не можем модифицировать, так что это не решение.
Я также понимаю точку зрения Microsoft, поэтому я больше не настаиваю на этом (помимо того факта, что сохранение этой проблемы открытой дает ненужную надежду, которая не позволяет сопровождающим пакетам просто настроить сборку вместо того, чтобы ждать, пока TS решит это), это было бы быть потрясающим, хотя бы иметь только машинописный текст в качестве инструмента сборки и никаких других зависимостей.

да, но ясно, что надежда все еще хороша для многих людей

image

Тем не менее, в этих комментариях пару раз говорилось, что это НЕ будет реализовано, так зачем держать его открытым?

если кто-то пишет TypeScript, например import { ... } from './foo', а затем публикует это как пакет NPM

Много ли людей публикуют нескомпилированные TS в пакетах NPM? Я смотрел на это для моего собственного внутреннего использования. Я делаю библиотеки общего кода, совместно используемого между проектами, и решил, что NPM — разумный способ их упаковать, и наша команда перешла исключительно на TS, поэтому я был бы рад избежать необходимости компилировать deps. Но похоже, что наиболее распространенным вариантом использования является сборка пакета для JS с отдельными типизациями, затем указание modules или main на JS и types на типизацию.

Существует ли соглашение о публикации нескомпилированных TS в NPM? Если да, то это где-то задокументировано? Я понимаю, что это блуждающий OT из исходной проблемы, но я думаю, что это имеет отношение к ответу, потому что нам нужно знать, является ли «сторонний TypeScript» (пакеты) поддерживаемым вариантом использования / целью.

@ thw0rted Извините за неясность, я имел в виду:

... если кто-то напишет TypeScript как import { ... } from './foo' , а затем перенесет это в JS с помощью TSC сегодня и опубликует этот JS как пакет NPM...

Если это НЕ будет реализовано, я предоставлю MS закрыть вопрос сейчас.

А, теперь я понял. Да, когда я транспилирую (с target: ES2018 ), выпущенный JS оставляет расширение без оператора импорта, но это работает для меня, потому что потребитель помещает все через webpack/babel, и он должен заполнить отсутствующее расширение. для меня. Я в курсе. Мне даже не приходило в голову, что мой «пакет» не будет работать изначально в браузере без предварительного прохождения через веб-пакет.

Да, это тяжело.

@ thw0rted Я не использую webpack/babel, поэтому разрешение .js из коробки для меня проблематично.
Некоторым решением/обходным путем является настройка веб-сервера для разрешения источников по умолчанию .

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

Я знаю, что TypeScript не должен обслуживать какую-либо конкретную среду (Node.js, Webpack и т. д.), но факт в том, что существует множество сред, где расширение всегда необходимо, если только специально не настроено иное, поэтому я не не думаю, что их следует игнорировать. Импорт больше не скрывается в Node, и путь импорта должен соответствовать пути URL-адреса в Интернете. Хотя нет технической необходимости иметь .js в конце URL-адреса, это стандарт де-факто.

Если хорошие люди в Microsoft действительно хотят, чтобы расширение файла не было по умолчанию, я не буду спорить об этом. Вы, вероятно, умнее меня, но я, безусловно, был бы счастливее, если бы вместо того, чтобы делать выводы о том, нужны ли расширения на основе других импортов в том же файле, это можно было бы установить для всего проекта, чтобы оно работало для автозаполнения Intellisense для первого импорт добавлен в файл!

А пока кто-нибудь знает какие-нибудь плагины VSCode, которые это исправляют? Добавление импорта/расширений в eslint — лучшее, что я смог сделать, чтобы справиться с этим.

В настоящее время я пишу строки import без расширения .js, а затем использую sed для добавления расширения .js в выходные файлы.
https://github.com/yoursunny/NDNts/blob/9f50fcec245b33c7649fa815bbb3dd404eee160e/mk/build.sh#L12 -L14
Мне пришлось удалить SourceMaps во время производственной сборки, потому что они больше не будут совпадать после изменения выходных файлов.

Я не могу писать расширение .js в исходных файлах .ts, потому что оно ломает ts-jest .
Хотя Jest можно запускать на скомпилированных файлах .js, он ломает Coveralls .

@yoursunny Да, sed - это вариант (я тоже его использовал, но предпочитаю замену в файле из- за конфигурации, которую можно настроить с помощью сопоставления файлов importmap) для замены строк в сгенерированных js-файлах, но это плохо пахнет =) Может быть добавление расширений будет полезной функцией/опцией для ttypescript с плагином преобразования (например , typescript-transform-paths от @MicahZoltu).

@richardkazuomiller, эта часть не соответствует действительности:

Если хорошие люди в Microsoft действительно хотят, чтобы расширение файла не использовалось по умолчанию

Только TypeScript:

  1. Разрешает разрешение модуля в стиле Node-require (они должны расширить это, чтобы разрешить разрешение в стиле Node-импорта, для которого требуются расширения файлов).
  2. В той же единице компиляции разрешает файлы .js в пару .js/.d.ts еще до того, как они будут сгенерированы компилятором.
  3. Не изменяет спецификаторы импорта _вообще, никогда_.

Таким образом, решение всего этого — просто импортировать файлы .js с расширением .js . TypeScript будет разрешать правильный файл .ts и не будет изменять спецификатор импорта, поэтому все будет работать в браузерах и Node >= 13.2.

@yoursunny вы сообщили об ошибке в ts-jest ? Здесь они расходятся с де-факто стандартом TypeScript. Также похоже на ошибку в Coveralls, если он не может использовать исходные карты в файлах .js.

вы зарегистрировали ошибку против ts-jest ? Здесь они расходятся с де-факто стандартом TypeScript.

Нет, потому что я не совсем понимаю, как работает разрешение ts-jest.

Также похоже на ошибку в Coveralls, если он не может использовать исходные карты в файлах .js.

Coveralls получает отчет lcov из моего процесса сборки, а затем отображает покрытие кода, используя файлы, зафиксированные на GitHub.
Я не передаю выходные файлы .js на GitHub. Если я запускаю модульное тестирование файлов .js, отчет lcov будет ссылаться на файлы .js, которых нет на GitHub.
Таким образом, Coveralls не может найти исходные файлы. Он будет отображать процент покрытия, но не может показать, какие линии не покрыты.

Наступила новая эра!

Недавно выпущенный Node.js v13 и все основные браузеры поддерживают собственные модули ES «из коробки», и было бы здорово, если бы TypeScript поддерживал эти среды простым способом.

Самым простым решением для самых простых случаев использования (веб-сайт, обслуживаемый через простой статический файловый сервер) было бы добавить новый параметр компилятора, такой как "appendJsExtension": true или аналогичный.

@mjbvz Проблема в репозитории VS Code, который вы закрыли, немного отличается: речь идет об использовании автозаполнения для автоматического добавления операторов импорта; когда VS Code делает это, добавляет оператор импорта без расширения .js , и это легко пропустить до сбоя во время выполнения.

Однако если TypeScript добавит такую ​​опцию, как "appendJsExtension": true или аналогичную, то это не будет иметь большого значения, и мы сможем написать код TS без .js в исходном коде.

Может быть, плагин VS Code должен иметь возможность включать/отключать автоматическое добавление расширений .js в автоматически заполняемые операторы импорта?

@mjbvz Проблема VS Code / Intellisense связана, но ее не следует закрывать как обман. Если эта проблема в конечном итоге будет закрыта как WONTFIX, это фактически повысит важность проблемы VS Code.

Я упускаю из виду один момент и не понимаю, как решения, в которых расширение JS имеет особый случай, решат эту проблему: для ESM ни одно расширение не имеет особого статуса, даже файлы без расширений полностью в порядке, пока сервер передает их браузеру с помощью соответствующий тип MIME text/javascript. Это означает, что такой код, как:

import something from './javascript-code.png';
import something2 from './javascript-code2.js';
import something3 from './javascript-code3.ts';

Все это действительно до тех пор, пока файлы (независимо от их расширений) содержат код JavaScript и передаются в браузер с типом MIME JavaScript.

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

Итак, решения, в которых расширение JS либо подразумевается, либо разрешено только одно, я не думаю, что могут сократить это? Более того, даже расширения TS и DTS IMO не могут быть помещены в специальный регистр, потому что, хотя обычно это не так, они могут содержать код JavaScript, а не код TypeScript и сервер для браузера как таковой без каких-либо проблем с точки зрения ESM. , если они обслуживаются с правильным типом MIME.

Я что-то упускаю на этом фронте? Возможно ли, чтобы TypeScript не реализовывал поддержку произвольных (в том числе отсутствующих) расширений при импорте кода, и возможно ли, чтобы TypeScript продолжал принимать расширения TS при импорте модулей, учитывая, что file.ts и file (без расширения) приведет к конфликту?

Web и Service Workers также получают поддержку импорта/экспорта модуля ES .

Я полностью поддерживаю и одобряю идею @trusktr о реализации их идеи в качестве опции компилятора. Дело не в том, что я хочу избавиться от сборщиков, таких как webpack и rollup. Но я верю, что подобная функция избавит вас от многих хлопот и времени, затрачиваемого на настройку упаковщиков, когда все, что вам нужно, это скомпилировать простой проект Typescript без прыжков через обручи или использования неудобных обходных путей.

Пожалуйста, рассмотрите это как вариант для компилятора Typescript. <3

Кто-нибудь знает, как вы можете запускать скомпилированные отдельные файлы js в браузере без веб-пакета или --outFile , используя любую модульную систему?

Моя проблема заключается в следующем: довольно большой проект TypeScript, с которым я работаю, требует около 35 секунд для компиляции с веб-пакетом в связанный файл js с использованием ts-loader .
Единственный способ оптимизировать это — использовать transpileOnly , что сокращает время компиляции до 20 секунд, но это все еще медленно, и я теряю проверку типов.
Избавившись от webpack, я мог бы получить около 14 секунд, используя outFile, но это все еще слишком медленно для меня. Использование incremental не имело никакого значения.

Единственный способ, которым я мог получить несколько секунд времени компиляции, - это создать 1 файл js на 1 файл ts и использовать флаг incremental . В этом случае я предполагаю, что ts обнаруживает и компилирует только те файлы, которые действительно изменились. Проблема в том, что я не смог запустить это в браузере ни в одном из целевых модулей, которые я пробовал: system, amd, es6.
Я использую сопоставление paths в tsconfig.json , и в скомпилированных файлах js ошибки, которые я получаю, в основном связаны с невозможностью разрешить эти псевдонимы.

Есть ли способ добиться этого?

@andrewvarga В настоящее время я запускаю весь свой скомпилированный TypeScript непосредственно в браузере без связывания или компиляции в один файл. Самый простой способ сделать это:

  1. Убедитесь, что все импортируемые файлы TypeScript имеют расширение .js .
  2. Запустите сервер разработки, который разрешает импорт имен пакетов npm для зависимостей, если это необходимо. es-dev-server — самое простое, что я знаю.
  3. Запустите tsc --watch (убедитесь, что в вашем tsconfig указан модуль esnext )

Вот и все. Если вы просто напишете расширение .js для импорта в своем TypeScript, вам не понадобятся другие инструменты для исправления файлов для браузеров.

@justinfagnani приятель, ты забыл самую важную часть информации - типы должны быть в формате jsdoc, любая абстракция машинописного текста по сравнению с нативным JavaScript приведет к сбою синтаксического анализатора.

@Draccoz tsc будет выводить JavaScript, а не TypeScript.

@andrewvarga Самый простой известный мне способ транспиляции без связывания — это мой проект Zwitterion . Он предназначен для замены статического файлового сервера, поэтому вам не нужно менять способ разработки. Вы можете импортировать и экспортировать с явными расширениями файлов (.js для JavaScript и .ts для TypeScript) даже в элементах сценария. Он очень производительный, выполняет кэширование и автоперезагрузку при изменении файлов. Вам придется полагаться на свой редактор для статического анализа (ошибки типа), хотя

@andrewvarga Я использую https://github.com/Zoltu/typescript-transformer-append-js-extension/ и нацеливаюсь на собственные модули ES, которые загружаются во всех современных браузерах (кроме Safari, нового IE).

Если ваши зависимости NPM во время выполнения довольно ограничены, вы можете загрузить их с помощью es-modules-shim без какой-либо сборки. Вы можете увидеть созданный мной шаблон реакции, который показывает, как все это работает вместе: https://github.com/Zoltu/react-es2015-template

@MicahZoltu Safari поддерживает модуль ES, я знаю это точно, основываясь на Caniuse и личном опыте: https://caniuse.com/#search =modules

@justinfagnani awww извините, я пропустил часть «скомпилированного TypeScript», думал, вы говорите о машинописном тексте jsdoc.

Всем спасибо за разные советы!

Я обнаружил, что использование модуля hard-source-webpack-plugin npm для веб-пакета и transpileOnly: true в параметрах ts-loader сокращает время сборки примерно до 4-5 секунд.
Это, конечно, будет игнорировать ошибки машинописного текста, поэтому это полезно только для быстрых итераций сборки, проб в браузере и использования IDE для любых потенциальных ошибок, но я думаю, что это очень полезно во время разработки.

Чтобы получить как ошибки TS, так и быструю компиляцию, я все еще думаю, что единственным способом будет запуск модулей в браузере, но отсутствие поддержки import-maps и js-расширений усложнило это.
@justinfagnani @MicahZoltu спасибо, я попробую эти варианты. В целом я предпочитаю избегать использования еще одного модуля npm, но это кажется неизбежным.

Я пытался заставить его работать и с помощью systemjs, но застрял с картами импорта.

@andrewvarga Вы можете попробовать SystemJs на моем легком примере с importmap.
Вы также можете попробовать мой тяжелый пример — альтернатива systemjs и esm, но esm importmaps не поддерживаются нативными, и мы должны разрешать модули вручную (gulp-replace), или вы можете попробовать es-module-shims .

Поэтому, если я использую tsc в качестве единственного компилятора, ориентируясь на esnext или es2015 в качестве типа модуля. Есть ли способ использовать вывод прямо в моем браузере?

https://github.com/alshdavid-sandbox/typescript-only-compiler

Если я правильно понимаю остальную часть этого потока, Typescript должен быть совершенно счастлив скомпилировать ваш код, если вы измените эту строку на from "./module.js" . Тогда скомпилированный index.js будет иметь допустимый оператор импорта ES6, и все должно работать.

Это если вы не импортируете какую-то библиотеку, которая либо не знает, как импортировать ES, либо не заботится: P.

Я создал плагин для Gulp, который добавляет .js для импорта путей к файлам. (также бонусное разрешение пути).

Я использовал Gulp, потому что я не знаю другого средства запуска задач, которое позволило бы мне по существу присоединить простой шаг постобработки к компилятору tsc (как в режиме просмотра, так и в обычном режиме). Webpack и rollup являются эксклюзивными пакетами, и я хочу выпускать модули es.

Это работает, но смотреть на это медленно, так как кажется, что он восстанавливает все это.

https://github.com/alshdavid-sandbox/typescript-only-compiler/tree/gulp

Это становится все более важным, так как команда Node отказалась от импорта без расширений.
https://github.com/nodejs/modules/issues/444

Добавление карт импорта также решило отказаться от импорта без расширений.
https://github.com/WICG/import-maps/issues/194

Если мы хотим использовать модуль es, скомпилированный с помощью машинописного текста, в браузере или узле, нам нужно добавить расширения с помощью машинописного текста? (для внутренних модулей) и вручную для внешних модулей? @весвигем

@chyzwar еще раз, если вы просто напишите расширения .js в исходном коде TypeScript, то скомпилированный вывод будет иметь правильные расширения, и модули будут работать в браузерах и Node. Вам не нужны дополнительные инструменты преобразования или tsc , которые сделают что-либо за вас.

Разработчику проще сделать следующее: Если это исходный файл TypeScript, напишите расширение .ts. Если это исходный файл JavaScript, напишите расширение .js. Это также будет правильно компилироваться и работать в браузере (.ts потребуется тип MIME application/javascript). Расширение должно соответствовать типу исходного файла. Модули tsc и ES могут справиться с этим (по крайней мере, модули ES в браузере, надеюсь, Node.js следует тому же)

@justinfagnani tsc вполне доволен этим, и будет справедливо сказать, что «это не наша проблема», но, похоже, здесь нет единого мнения о том, что правильно,

Между tsc, vscode, webpack и ts-node ни один из них не может хорошо согласоваться со стандартом, который только сейчас становится доступным изначально (теперь доступны браузер и узел).

Пример 1

Я хочу написать современный пакет javascript, создать его в машинописном тексте и выделить типы для распространения в виде модуля ecmascript (сохранив операторы импорта и экспорта).

Пример 2

Я создаю статический веб-сайт с использованием модулей в vscode, по умолчанию он будет автоматически импортироваться без расширения для каждого первого импорта, и вам нужно настроить это вручную.

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

Но если я хочу запустить тестовый код для исходного кода, я мог бы использовать ts-node, но здесь ts-node не устраивает.

Точно так же тот факт, что tsc, vscode и webpack эволюционировали, чтобы делать следующее:

  1. vscode автоматически импортирует без расширения
  2. tsc с радостью перепишет импорт в файл js, имея в виду файл ts.
  3. webpack творит здесь различную магию для расширений по умолчанию для поиска

Все ли вещи, которые следует подвергнуть сомнению, теперь, когда все четыре реализации (chrome, firefox, safari, node) ожидают, что путь импорта должен указывать на что-то, что может быть разрешено непосредственно в файл.

Добавление .js к импорту должно быть временным обходным путем, а не окончательным решением. Во всяком случае, это похоже на взлом. Способ обмануть компилятор. И попытка перехитрить компилятор - ужасная идеология, имхо. Я могу только представить, насколько это должно сбивать с толку людей, плохо знакомых с Typescript. Язык, который должен помочь разработчикам Javascript писать _лучший_ код.

Как уже упоминалось, если вы добавите .js в импорт, TypeScript выведет их, и все будет работать (по крайней мере, в вашем коде). Рассуждение о том, что tsc должен добавлять расширения, потому что они не работают в браузере, похоже на то, чтобы просить TypeScript исправить ошибки времени выполнения, вызванные разработчиком - хорошо, но почему разработчик не может исправить их самостоятельно?
Не поймите меня неправильно, я бы хотел, чтобы tsc был моей единственной зависимостью от разработчиков, но некоторые вещи просто не произойдут и останутся мечтой.

Я бы хотел, чтобы tsc был моей единственной зависимостью от разработчиков, но некоторые вещи просто не произойдут и останутся мечтой.

Я, должно быть, видел десятки почти идентичных комментариев к № 3469 за несколько лет, в том числе некоторые из команды Typescript. «Это средство проверки типов, оно должно хорошо делать одну вещь, не ждите, что оно заменит всю вашу цепочку инструментов…» На это ушло 3 года, но они все же добавили режим сборки, потому что были сделаны убедительные доводы в пользу того, что он правильное направление.

Webpack и rollup являются эксклюзивными пакетами, и я хочу выпускать модули es.

@alshdavid Rollup может работать на вас, если вы установите формат вывода на esm и установите для preserveModules значение true : https://rollupjs.org/guide/en/#preservemodules

возможно, импорт «без расширений» был первородным грехом, несовместимым с тем, как будут работать браузеры.

теперь пришло время исправить наш исходный код и включить расширения .js : мы обнаружили, что когда вы сегодня добавляете расширения .js в свой исходный код, все работает: браузер удовлетворен, машинописный текст не зависит, и сборщикам все равно

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

Написание расширения .js в импорте в исходном коде машинописного текста — полная ерунда. Он работает, он сохраняет расширение в выходных данных, но, вероятно, произойдет сбой из-за ошибок «не удалось разрешить файл» в правилах ESLint (или TypeScript) в VSCode или любом другом редакторе, который вы используете. Не говоря уже о том, что вы тестируете исходный код машинописного текста. Тогда инструмент тестирования также должен знать об этом дерьмовом поведении. Я почти уверен, что он выдаст ошибки, что не может разрешить файлы.

Базовый пример

src/index.ts
src/foo.ts
test/index.ts

источник/foo.ts

export default (a: number) => a + 100;

источник/index.ts

// okay, editor (without ESLint) doesn't report error here
import foo from './foo.js';

export default () => {
  console.log(foo(123));
}

тест /index.ts

// errm... ts or js ext?! .ts should be the one that make sense
// and that's how the testing too will expect it to be, otherwise will throw
// but then it will detect some weird `.js` ext in the source files...
// which again won't be able to resolve... complete bullshit. 
import main from '../src/index.ts';
import foo from '../src/foo.ts';

test('some boolshit', () => {
  main();
});

test('about foo', () => {
  foo(20);
});

Извините за "чушь", но это правда.

Я не думаю, что это так уж сложно реализовать базовую опцию, когда компилятор видит расширение ( .ts ) в импорте, чтобы преобразовать его в .js (или даже опционально разрешить указать, что выходное расширение для быть). Когда расширения нет, не сохраняйте расширения (полутекучее поведение?).

Написание расширения .js в импорте в исходном коде машинописного текста — полная ерунда. Он работает, он сохраняет расширение в выходных данных, но, вероятно, произойдет сбой из-за ошибок «не удалось разрешить файл» в правилах ESLint (или TypeScript) в VSCode или любом другом редакторе, который вы используете.

Это просто неправда. ESLint, TypeScript, VS Code и любой другой инструмент, связанный с TypeScript, который я использовал, _просто работал_ с этим методом. Это не взлом, и у него есть очень разумное обоснование: файл, который вы импортируете, на самом деле _является_ файлом .js , и что ваши расширения не должны меняться только потому, что импортированный файл является частью локального проект или предварительно скомпилирован как часть стороннего пакета.

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

Нет, это не так. По крайней мере, в наиболее распространенном случае, когда выходной каталог dist или build или lib и т. д. Ваши скомпилированные файлы не находятся в одном каталоге, они просто никогда не существуют там (в src/ ) - ни при тестировании, ни при кодировании в редакторе.

Иметь/видеть и импортировать ./foo.js в приведенном выше src/index.ts не имеет для меня НИКАКОГО смысла - если, конечно, вы действительно не хотите импортировать файл js/json, что совершенно нормально. Но написать ./foo.js , когда вы действительно имеете в виду другой исходный файл машинописного текста ( ./foo.ts ), это... жестоко. Это вводит в заблуждение и сбивает с толку, и определенно неправильно.

Я почти уверен, что если я запущу указанный выше test/index.ts с помощью Jest, произойдет сбой с ошибкой, из-за которой он не сможет найти/разрешить ./foo.js , потому что существует только ./foo.ts .

Если оставить все в стороне, то почему разрешено иметь расширение .js , а не .ts (ts сообщает об ошибке в редакторе)? Это элементарное, простое и глупое несоответствие. Как и многие другие проблемы «просто потому что» в TypeScript.

Я на самом деле потерял логику, почему эта проблема называется именно так, когда на самом деле можно закончить с расширением .js . Я думаю, что проблема в полной противоположности - она ​​не может заканчиваться на .ts (начиная с 3.7+)

почему расширение .ts в импорте полностью запрещено?!

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

TypeScript — это надмножество JavaScript, но это не JavaScript. JavaScript является целью компиляции для TypeScript.

Имея это в виду, несмотря на то, что TS будет компилироваться в JS, я ожидаю, что код TypeScript будет вести себя как полностью автономное поместье.

Написание .js при попытке импортировать файл .ts предполагает знание целевого типа компиляции и предполагает, что целью компиляции всегда является JavaScript.

Что, если мы скомпилируем TypeScript в двоичный файл веб-сборки или запустим код TypeScript, используя альтернативную среду выполнения, такую ​​как Deno или ts-node.

Операторы импорта, оканчивающиеся на .js , не имеют смысла в таких контекстах.

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

Печально, что typescript изобрел собственное расширение вместо того, чтобы быть просто синтаксическим сахаром, таким как поток.

@phaux Я бы никогда не хотел работать с проектом, в котором смешаны исходные и дистрибутивные файлы с одним и тем же расширением, даже если они находятся в разных папках. Это все равно, что назвать все файлы index.js , только потому что они находятся в разных папках...

Эта проблема (которая больше, чем TypeScript), по-видимому, блокирует работу IntelliSense Visual Studio Code в веб-браузерах и Node, что требует полных (относительных) путей к файлам в спецификаторах импорта. Без этого сгенерированные операторы import , которые он создает, работают только с транспилерами и упаковщиками, такими как WebPack и сам TypeScript.

Ответ команды VSCode заключался в том, что расширения должны добавляться кодом, который предоставляет предложения по автоматическому импорту. Я подозреваю, что это сервер языка TypeScript (а не tsc , о котором здесь шла дискуссия).

Может ли кто-нибудь, кто действительно знает, подтвердить (или исправить), что VSCode получает предложения по автоматическому импорту от сервера языка TypeScript?

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

поэтому, возможно, мы рассматриваем текущую парадигму следующим образом:
импорт машинописного текста описывает то, что импортируется во время выполнения , то есть ваш импорт выполняется в вашем каталоге «dist», а не «src» — например, вызовы fetch и остальные — если мы можем терпеть эту идею, остальное становится простой и последовательный

кажется, безусловно, плохой идеей иметь машинописный текст, слепо присоединяющий «.js» к импорту без расширений, как это делает node для commonjs (стоит отметить, что поддержка Node esm требует «.js» так же, как и машинописный текст сегодня) — слепое присоединение «.js» создадут новые проблемы, такие как импорт файлов javascript без расширений или даже других типов файлов, таких как css или json, — это сделает расширения значимыми и потребует специальной логики синтаксического анализа, создав резкое различие между семантикой браузера и машинописного текста — и мы, очевидно, не собираемся переписать вызовы fetch таким же образом, поэтому, может быть, import должны оставаться похожими?

однако мне интересно - относительно безвредно для машинописного текста преобразовывать расширения ".ts" в ".js"?

конечно, это сделало бы невозможным импорт файла javascript с расширением «.ts» — но, может быть , это немного фанк-волшебства, которое мы могли бы терпеть? с другой стороны, это причудливая магическая идиосинкразическая разница между семантикой браузера и машинописного текста, которую разработчикам придется изучить и понять (конечно, создав странные ошибки) — так что мой инстинкт — оставить вещи там, где они есть сегодня.

с другой стороны, если мы оставляем все как есть, волшебство просто перемещается в машинописный текст, который должен связать импорт ".js" с соответствующими исходными файлами ".ts" - мне кажется, это более разумное место для храните волшебство, будучи внутренним для машинописного текста, а не попирая семантику браузера

🥃 погоня

@rconnamacher , @TomasHubebauer

Эта проблема (которая больше, чем TypeScript), по-видимому, блокирует работу IntelliSense Visual Studio Code в веб-браузерах и Node, что требует полных (относительных) путей к файлам в спецификаторах импорта. Без этого сгенерированные операторы импорта, которые он создает, работают только с транспиляторами и упаковщиками, такими как WebPack и сам TypeScript.

я думаю, что здесь просто некоторая путаница — сегодня вполне возможно создать библиотеку или приложение машинописного текста, которое отлично работает с vscode и intellisense, которое работает в браузерах и узлах и работает в esm или commonjs — действительно универсальное решение возможно сегодня

я работал над несколькими открытыми библиотеками, которые демонстрируют это — renraku , cynic , redcrypto , авторитарная

Напишите мне по электронной почте, и я буду рад объяснить больше

:волна: погоня

Другой момент заключается в том, что это приводит к путанице в том, к какому файлу вы обращаетесь. Уже существует двусмысленность того, что tsc смотрит после разрешения модуля, когда у вас есть файлы .js и .ts рядом.

/folder
  a.ts
  a.js
  index.ts

Если в index.ts , при использовании moduleResolution: 'node'

// points to a.ts
import * as a from './a` 

// points to a.ts
import * as a from './a.js` 

// compiler emits error
import * as a from './a.ts` 

Уже существует двусмысленность того, что tsc смотрит после разрешения модуля, когда у вас есть файлы .js и .ts рядом.

Хорошо, конечно, но если a.js не является транспилированной версией a.ts , то что-то пошло катастрофически не так, и это не вина TypeScript.

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

Это не "незаконно", но это не значит, что это хорошая идея. У вас есть конкретный пример того, где вы на самом деле хотите этого?

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

Например:
https://github.com/alshdavid/tsc-веб-сайт

Но я чувствую боль проблемы. Команда TypeScript не хочет реализовывать разрешение модулей. По той же причине компилятор TypeScript не может преобразовать paths в их фактические относительные пути во время компиляции.

Преобразование импорта из .ts в .js или добавление .js в импорт без расширения означает, что команда TypeScript реализует разрешение модуля, а это выходит за рамки.

Решение для этого состоит в том, чтобы команда TypeScript предоставила способ введения расширений, чтобы мы могли реализовать эти вещи.

Решение для этого состоит в том, чтобы команда TypeScript предоставила способ введения расширений, чтобы мы могли реализовать эти вещи.

Да, просто через tsc он не выставляется (только через программный вызов компилятора). К счастью, кто-то создал оболочку вокруг основного компилятора, которая работает точно так же, как tsc , за исключением того, что она поддерживает расширения через конфигурацию. Используя эту оболочку tsc, вы можете использовать расширение, например https://github.com/Zoltu/typescript-transformer-append-js-extension/ , для автоматического добавления расширения .js .

@alshdavid ваш пример в GitHub работает в браузерах без сборщика, если вы просто включите расширение .js при импорте. Я подал PR, чтобы исправить это.

@alshdavid Может быть, вам будет интересен мой пример проекта (esm для современного и IE11 с SystemJS).
Но я вынужден разрешать модули esm вручную =(

В принципе у меня нет проблем с размещением .js во всех моих import , но, к сожалению, это приводит к плохому взаимодействию с некоторыми инструментами. Например, ts-node задыхается: https://github.com/TypeStrong/ts-node/issues/783. Кажется, нет четкого соглашения о том, чья это ответственность - TypeScript выдавать расширение .js (при некоторых обстоятельствах) или каждый инструмент, который использует исходники TypeScript для выполнения перевода. И пока все перекладывают ответственность на других, пользователи страдают от плохо документированных плагинов или неуклюжих сервисных работников, которые пытаются обойти несовместимости взаимодействия.

Есть ли обновления по этому поводу? Честно говоря, я не могу поверить, что сегодня невозможно просто нормально использовать TypeScript без внешнего загрузчика модулей или сборщика, такого как Webpack. Это кажется мне таким странным, а также расстраивающим. Если мне нужно использовать какой-то внешний модуль, чтобы заставить TypeScript полноценно работать, то его следует запустить.

Я пытаюсь использовать это в своем приложении Electron, поэтому я не вижу причин для использования веб-пакета, и я также хотел бы не устанавливать внешний загрузчик модулей, если он не нужен. Но это сводит меня с ума. Невозможно даже запустить базовую настройку TypeScript + Electron, хотя оба они везде хвалят как лучшее решение. Это безумие, если честно. Я не знаю, может я что-то упускаю, но неспособность найти адекватное решение более чем расстраивает.

И если это действительно не я, то я не понимаю, почему этот вопрос не решается за 3 года ...

Недавно я завершил учебник по машинописному тексту, а затем, когда я попытался создать несколько файлов ts, я столкнулся с этой проблемой. Я совершенно новичок в этом мире js-ts, поэтому извините меня, если что-то не так или вводит в заблуждение/дезинформированно.

то, что я сделал, было при импорте

Я просто добавил расширение .js в файл ts , а затем, когда я проверил intellisense, он сработал, и когда я перенес его с помощью tsc, он также добавил расширение .js в сгенерированный выходной файл.

Вот что я сделал.
tsc -p tsconfig.json

{
"Параметры компилятора": {
//"модуль": "амд",
"модуль": "es6",
"цель": "es6",
"noImplicitAny": ложь,
"удалитькомментарии": правда,
"preserveConstEnums": ложь,
//"outFile": "js",
"outDir":"js",
"исходная карта": ложь
},
"включать": [
"testscript.ts"
]
}

Хотя у меня сработало.

Я сомневаюсь, что, поскольку нет svgwrapper.js для импорта из
почему / как это сработало? (Я предполагаю, что он не рассматривает расширение)

Я прилагаю скриншот для справки.

ts-js-ext-issue

@yogeshjog именно так и должно работать tsc . Вы импортируете модуль с именем файла, которое будет сгенерировано. Импортируемый модуль изначально записан как файл .ts или как пара .d.ts / .js , не должно быть видно из модуля импорта.

@yogeshjog именно так и должно работать tsc . Вы импортируете модуль с именем файла, которое будет сгенерировано. Импортируемый модуль изначально записан как файл .ts или как пара .d.ts / .js , не должно быть видно из модуля импорта.

Спасибо! @justinfagnani для уточнения 👍

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

Но TypeScript также позволяет опускать расширение, что не допускается согласно ECMAScript. Он даже опускает расширение при использовании функции автоматического импорта в VSCode, что больше всего раздражает. Вы пишете какой-то JS, а TS говорит, что все в порядке, а затем происходит сбой во время выполнения.

Но TypeScript также позволяет опустить расширение

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

что не разрешено в соответствии с ECMAScript.

ECMAScript ничего не говорит о спецификаторах импорта. Это остается за размещением таких сред, как HTML и Node. TypeScript поддерживает разрешение узла при загрузке модулей и интерпретирует разрешение относительно компилятора _output_, а не компилятора _input_. Таким образом, спецификаторы работают после компиляции и работают независимо от того, пытаетесь ли вы импортировать скомпилированный модуль или нет.

Поскольку TypeScript использует разрешение узла, которое будет выполнять поиск пути, чтобы превратить информацию './foo' './foo.js' , './foo' является допустимым. Но разрешение узла не превратит './foo.ts' в './foo.js' , поэтому './foo.ts' недействительно.

Но это в пределах разрешения Node. Если вы пытаетесь использовать другую среду, например HTML или встроенную поддержку модулей Node, то TypeScript и хост не согласятся с тем, что допустимо.

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

@leontepe Вам не нужен упаковщик/загрузчик. Вы можете либо использовать https://github.com/Zoltu/typescript-transformer-append-js-extension/ (мое предпочтительное решение), либо добавить .js ко всем вашим операторам импорта (остерегайтесь: это приведет к сделать ваш код неудачным в ts-node ).

@leontepe Вам не нужен упаковщик/загрузчик. Вы можете либо использовать https://github.com/Zoltu/typescript-transformer-append-js-extension/ (мое предпочтительное решение), либо добавить .js ко всем вашим операторам импорта (остерегайтесь: это приведет к сделать ваш код неудачным в ts-node ).

@MicahZoltu Что ж, спасибо, но все же немного расстраивает, что это не работает «из коробки». Как сказал @phaux , VSCode предлагает своим пользователям делать операторы импорта без расширения, и это просто не работает во время выполнения. Я серьезно сомневаюсь в компетентности команды TypeScript здесь, или я все это время ошибался, и я просто глуп. Но кто знает...

Редактировать: на данный момент серьезно рассматриваю возможность просто отказаться от TypeScript для JavaScript + Babel.

Я не писал приложение Electron, но есть ли возможность заставить его делать разрешение в стиле Node, где есть алгоритм для попытки разрешения импорта, который пробует несколько вещей в фиксированном порядке? Похоже, все должно быть в порядке, учитывая, что все исходники загружаются из локальных ресурсов...

Может пора добавить в TS новое разрешение модуля? Node.js теперь имеет встроенную поддержку ESM, но без явных расширений в относительных путях приходится использовать флаг --experimental-specifier-resolution=node , что несколько раздражает. Также есть Deno и браузеры. В идеале должно быть что-то вроде этого:
tsconfig.json:

{
    "compilerOptions": {
        "moduleResolution": "explicit",
        "strict": true
    }
}

затем машинопись:

import foo from './foo.ts'; // no ts(2691) here

компилируется в Javascript:

import foo from './foo.js';

"strict": true означает много работы!
2020, до сих пор не исправить, смешно.

Просто вмешиваюсь, чтобы сказать, что эта проблема также блокирует нашу команду 😢

Нам бы очень хотелось иметь единый исходный код, который строит собственные модули, а также используется в узле и с помощью веб-пакета. У Webpack, похоже, есть проблема, если вы вручную помещаете .js в свой импорт в своем коде TS. Тем не менее, вы можете заставить веб-пакет работать, если вы поместите расширение файла .ts в свой импорт, но, конечно, машинописный текст жалуется. Отсутствие расширения файла приводит к отсутствию собственных модулей. Таким образом, ни одна комбинация не удовлетворит браузер и сборщиков. Если бы мы могли написать .ts в нашем импорте и сделать его .js на выходе, я думаю, проблема была бы решена (и вы также получили бы deno compat). Что-то вроде @evg656e предлагает, кажется, что это должно работать.

@EisenbergEffect есть ли для этого ошибка в WebPack? Действительно звучит так, будто проблема WebPack отличается от обычного tsc.

@justinfagnani Я не уверен, что проблема в webpak, ts-loader или где-то еще. Я потратил много времени, пытаясь настроить оптимальную сборку, и не нашел решения, которое соответствовало бы всем требованиям. Вероятно, есть способы сделать это с помощью пользовательских преобразователей или шагов после сборки, но я не хочу использовать нестандартные настройки, поскольку это может негативно повлиять на последующих разработчиков.

@EisenbergEffect , если загрузчик TypeScript WebPack не позволяет импортировать файлы TypeScript через расширение $#$ .js tsc , то это ошибка. Как вы сказали, такое поведение не позволяет использовать одну и ту же исходную сборку с WebPack и tsc .

Может пора добавить в TS новое разрешение модуля? Node.js теперь имеет встроенную поддержку ESM, но без явных расширений в относительных путях приходится использовать флаг --experimental-specifier-resolution=node , что несколько раздражает. Также есть Deno и браузеры. В идеале должно быть что-то вроде этого:
tsconfig.json:

{
    "compilerOptions": {
        "moduleResolution": "explicit",
        "strict": true
    }
}

затем машинопись:

import foo from './foo.ts'; // no ts(2691) here

компилируется в Javascript:

import foo from './foo.js';

Люди (например, я) хотели бы, чтобы один фрагмент кода работал в Node.js, Deno и в Интернете одновременно. Я думаю, что это станет важной вехой для программирования на TypeScript/JavaScript.

Если вы используете vscode и вам нужно временное решение, добавление этого в settings.json , похоже, устраняет проблемы:

"typescript.preferences.importModuleSpecifierEnding": "js"

Он добавит .js к вашим путям импорта (что разрешит файлы *.ts в src без ошибок, но сохранит .js при переносе). Это полезно при использовании tsc без упаковщика.

Пока мы ждем решения tsc, низкотехнологичное решение этой проблемы состоит в том, чтобы

  1. Скопируйте все исходные файлы во временную папку
  2. Удалите расширение для импорта и экспорта перед сборкой

Я хотел поделиться этим однострочником на случай, если другие смогут его использовать. Он копирует папку src/ в tmp/ и изменяет там файлы.

npx shx cp -r ./src/ ./tmp/ && npx rexreplace "(^§s*?(?:import|export).*?from§s+?(['\"]).*?)§.ts§2" €1€2 './tmp/**/*.{ts,js,tsx,jsx}'

Как часть сценария сборки в package.json (после выполнения yarn add --dev shx rexreplace ) это может выглядеть так:

"scripts":{
  "build": "yarn build-esm && yarn build-tsc",
  "buil-esm": "...Whatever you normally do...",
  "build-tsc": "shx mkdir -p tmp && shx cp -r ./src/* ./tmp && rexreplace \"(^§s*?(?:import|export).*?from§s+?(['\\\"]).*?)§.ts§2\" €1€2 './tmp/**/*.{ts,js,tsx,jsx}' && tsc src/index.ts && shx rm -r ./tmp"
}

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

tsc -b tsconfig-solution.json -w --listEmittedFiles \
  | node mk/build-post.js

Сценарий постобработки build-post.js делает следующее.

Добавьте .js к import и export относительных путей

Например,

export { X } from "./first";
import { Y } from "./second";

становится

export { X } from "./first.js";
import { Y } from "./second.js";

Обратите внимание, что я нигде не использую index.ts , а вместо этого использую mod.ts соответствии с соглашением Deno. Таким образом, мне не нужно рассматривать случай добавления /index.js .

Измените import на require для пакетов CommonJS.

Мой код работает на узлах ^ 12.17 и ^ 14.1 в режиме модулей. Я публикую только модули ES.
Однако во многих зависимостях CommonJS все еще есть в поле "main" .
Таким образом, я должен изменить их на CommonJS, за исключением встроенных модулей NodeJS.

Например,

import { Server as WsServer } from "ws";

становится

import { createRequire } from "module";
const require = createRequire(import.meta.url);
const { __importDefault } = require("tslib");

const { Server: WsServer } = require("ws");

Но тогда webpack недоволен этими require s, поэтому я должен использовать:

/// #if false
import { createRequire } from "module";
const require = createRequire(import.meta.url);
const { __importDefault } = require("tslib");
/// #endif

/// #if false
const { Server: WsServer } = require("ws");
/*
/// #else
import { Server as WsServer } from "ws";
/// #endif
/// #if false
*/
/// #endif

В webpack любой пакет, импортирующий мой проект, должен использовать ifdef-loader , и тогда webpack увидит исходную строку import .

Мы также пострадали от этого, и я не могу понять, как это не исправлено через 3 года после сообщения.
Мы используем WebStorm, поэтому настройка VSCode не будет работать.
Использование отдельного скрипта для исправления вывода нелепо.
Это должно работать без использования сторонних инструментов.

+1

Это мой обходной путь с использованием веб-сайта asp.net core 3.1 (вероятно, работает в более низких версиях)
В файле startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            var rewriteOptions = new RewriteOptions();
            rewriteOptions.AddRewrite(@"^js/(.+)", "js/$1.js", skipRemainingRules: true);

            app.UseRewriter(rewriteOptions);

            app.UseStaticFiles();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }

Промежуточное ПО для перезаписи добавит расширение «.js» к любому запросу, нацеленному на папку /js.
Предупреждение: порядок промежуточного программного обеспечения здесь имеет значение, UseStaticFiles должен располагаться после UseRewriter, иначе он не будет работать.

Как и все здесь, я бы предпочел готовое решение, но до тех пор...

Может пора добавить в TS новое разрешение модуля? Node.js теперь имеет встроенную поддержку ESM, но без явных расширений в относительных путях приходится использовать флаг --experimental-specifier-resolution=node , что несколько раздражает. Также есть Deno и браузеры. В идеале должно быть что-то вроде этого:
tsconfig.json:

{
    "compilerOptions": {
        "moduleResolution": "explicit",
        "strict": true
    }
}

затем машинопись:

import foo from './foo.ts'; // no ts(2691) here

компилируется в Javascript:

import foo from './foo.js';

Я установил правило node/file-extension-in-import в eslint-plugin-node для linting config с идеей вручную добавить расширение для операторов импорта (так как это лучше) и "moduleResolution": "node" в TypeScript config и все, что я вижу, это ts(2691) .

Надеюсь, то, что сказал @evg656e , может стоить реализовать.

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

когда вы используете
"baseUrl": ".", "paths": { "/*": ["./*"] },

вы можете сделать импорт модуля absoulte следующим образом:
`импортировать ws из "/hey/connection";

но при добавлении расширения «.js» компилятор внезапно больше не находит объявление connection.ts и говорит:

Could not find a declaration file for module '/hey/connection'. '/home/tobi/Documents/JITcom/Code/Libs/Test_Browser/hey/connection.js' implicitly has an 'any' type.

используя относительный путь, все работает нормально.

Пожалуйста, исправьте это

Я также хочу исправить это.

Спасибо.

Смешно, что это до сих пор актуально! :00

Наконец-то я решил перейти на TypeScript, и это была одна из первых проблем, с которыми я столкнулся. Это нарушает разрешение модуля в собственной реализации Node, и я смог обойти это только с помощью пакета esm, который кажется более гибким в принятии имен без расширений, или (как ни странно) с использованием расширений .js в путях импорта внутри моих файлов .ts, даже если импорт относится к файлу .ts или .tsx. Я не уверен, почему компилятор TypeScript принимает это, но, по крайней мере, выходные данные сборки включают расширение .js. Ужасно хакерское решение.

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

Я отключил расширение в строках импорта, чтобы сделать Jest и Webpack счастливыми.
При компиляции я вызываю tsc --listEmittedFiles и передаю результат в скрипт постобработки. Этот скрипт добавляет расширения .js , чтобы сделать Node (в режиме модуля) счастливым.
https://github.com/yoursunny/NDNts/blob/fa6b2eb68a9f32a6a2e24e5475275f803236b8f8/mk/build-post.js

@kj

(странно) использование расширений .js в путях импорта внутри моих файлов .ts, даже если импорт относится к файлу .ts или .tsx. Я не уверен, почему компилятор TypeScript принимает это, но, по крайней мере, выходные данные сборки включают расширение .js. Ужасно хакерское решение.

Это не странно и определенно не хакерски, и отлично работает с браузером и собственным разрешением модуля Node.

Ресурс, который вы импортируете, _является_ файлом .js. Тип может быть либо в файле .ts, либо в файле .d.ts. Файлу .d.ts даже не обязательно быть одноуровневым с модулем .js, и между файлами .d.ts и файлами .js не должно быть однозначного отношения.

Импорт модуля .js — самый надежный и стабильный вариант, который могла выбрать tsc. В противном случае были бы случаи, когда вы импортируете типы, а tsc не знает, как правильно переписать их в фактический путь к модулю.

@justinfagnani А, думаю, в этом есть смысл. Я не имел в виду, что все, что здесь делает TypeScript, было хакерским (я не в том положении, чтобы делать подобные заявления), просто я чувствовал, что то, что я делаю, может быть нетипичным. Я думаю, что я думал об этом неправильно, хотя. Это не TypeScript импортирует модуль, это то, что оценивает вывод сборки (или я неправильно понимаю)? В этом случае я понимаю, почему это работает именно так.

Ресурс, который вы импортируете, _является_ файлом .js

Вы имеете в виду встроенный модуль, верно? Не файл .js в исходном каталоге, а встроенная версия модуля .ts?

Не может ли быть так, что если вы явно укажете расширение .ts или .tsx в пути к модулю, то вывод заменит .js?

Я думаю, что может быть неправильное понимание того, что происходит с @kj. Когда вы указываете расширение .ts без компиляции кода, оно ссылается на файл ts. Но когда вы компилируете с помощью tsc, он преобразует содержимое файла ts в файл js, исполняемый в среде, в которой вы находитесь (узел или браузер).

Я понимаю, что @mkay581 , но скажем, у меня есть эта строка в файле foo.ts:

import { Component } from './Component.js';

«Component.js», о котором я говорю, на самом деле является «Component.tsx» в файловой системе (файла .js нет, если только TypeScript не понимает, что это относится к возможной транспилированной версии файла?), тем не менее TypeScript отлично это воспринимает, и та же самая строка импорта присутствует в выводе (с расширением .js, которое затем работает с Node или браузером).

Традиционным способом TypeScript (AFAIK) было бы указать эту строку импорта без расширения, как:

import { Component } from './Component';

Это, очевидно, тоже хорошо компилируется, за исключением того, что строка импорта в транспилированном файле .js не включает расширение .js в «./Component», которое требуется в определенных средах (и, возможно, это звучит как спецификация, хотя я прочтите, чтобы быть уверенным).

С другой стороны, если я укажу строку с фактическим именем исходного файла:

import { Component } from './Component.tsx';

Затем TypeScript не распознает путь и предлагает мне попробовать строку импорта без расширения файла (если я правильно помню, я сейчас не за своим компьютером).

Итак, первый пример кажется мне немного странным, так как я пишу TypeScript, я ожидаю, что смогу импортировать с расширением .ts или .tsx, но он принимает только путь без расширения (что кажется расходится с другими реализациями модульной системы ES) или с расширением .js, которое может относиться только к выходному файлу, поскольку у меня нет такого исходного файла.

@justinfagnani

Ресурс, который вы импортируете, _является_ файлом .js.

Я не знаю, как работает tsc, но мне это кажется неправильным. Когда вы пишете свой код, файла .js еще нет. Задача компилятора — создать его.

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

Иными словами, когда вы используете C или C++, вы не #include .o в своем коде, вы включаете .h или максимум .c или .cpp .

Я готов принять разумное объяснение такого поведения в Typescript, но если я что-то не упустил, это, похоже, не то.

@kj

Это не странно и определенно не взломано

Жестко не согласен. Для меня это само определение странного и хакерского. 😛 Здесь вы ссылаетесь на гипотетический файл. Файл, существование которого не гарантируется. (Например, при связывании кода с использованием AssemblyScript или deno). Вы предполагаете выходной формат. Но при написании независимого кода (например, сторонних модулей) это _опасно_ предполагать.

@borfast @frzi Да, в основном, я так к этому отношусь, и я рад видеть, что я не единственный, кому это не нравится. Я просто пытаюсь не делать слишком много предположений, будучи новичком в TypeScript!

@frzi

Здесь вы ссылаетесь на гипотетический файл. Файл, существование которого не гарантируется

Не гипотетически, tsc знает, что сгенерирует его. Он гарантированно существует при использовании tsc.

Другой способ взглянуть на это так: если вы импортируете файл .ts, вы импортируете файл, которого не будет после компиляции.

при объединении кода

Бандлеры запускаются после tsc

@kj упомянул файлы .tsx, и они еще больше подтверждают мою точку зрения. .tsx существует только для того, чтобы сообщить компилятору этого модуля, _locally_, что модуль содержит JSX. Импортерам модуля не нужно знать, что в файле был JSX, и они не могут сказать после компиляции. Файлы можно легко переносить между парами .tsx, .ts и .js/.d.ts.

Допустим, вы импортируете файл .ts:

import {Component} from './component.ts';

Затем вы хотите использовать JSX для компонента, поэтому переименовываете его в component.tsx. Должен ли весь импорт потерпеть неудачу? Скажем, вы переходите с .ts на .js/.d.ts, если импорт снова не удастся?

@борфаст

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

Абстракция не так полна, как вы подразумеваете здесь. Вы можете импортировать файлы .js из вашего проекта TS или извне. Вы можете добавлять типы в файл .js с файлом .d.ts, который находится в любом месте вашего проекта. Файлы .js — это то, что реально после компиляции. Все остальное просто помогает компилятору.

@justinfagnani Я немного запутался в том, что вы говорите, но почему TypeScript не может просто предположить, что если вы укажете ему путь импорта с .ts или .tsx, он сгенерирует файл .js для этого модуля и поэтому следует заменить последнее расширение в выводе?

@justinfagnani

Не гипотетически, tsc _знает_, что сгенерирует его. Он гарантированно существует при использовании tsc.

Но здесь подразумевается симметрия, которую вы не признаете.

Эта «гарантия», которую вы упомянули, действительна в обоих случаях. Если, как вы говорите, «tsc _знает_, что он сгенерирует [файлы js]», то в равной степени уместно задать вопрос: «Ну, тогда почему tsc НЕ действует в соответствии с этой гарантией и не применяет расширения .js, которые он _знает_ отсутствует в скомпилированном js?»

Интерпретация того факта, что «tsc гарантирует js-файлы», работает в обе стороны.

Так что я согласен, @justinfagnani , ваша интерпретация _действительна_ с определенной точки зрения. Но противоположная интерпретация заключается в том, что «поэтому tsc должен _действовать в соответствии со своими знаниями_ и выполнять этот процесс для разработчика». И что меня беспокоит во всей этой дискуссии с самого начала, так это то, как _негативно_ воспринимается эта интерпретация, почти до такой степени, что ее высмеивают. Это неразумно.

В конце концов, этот спор касается _эстетического решения, а не логического_. И я надеюсь, что его хулители привнесут в этот вопрос ампликативный и уступчивый тон — как и подобает эстетическому мнению (а не логической дедукции).

Короче говоря, пожалуйста, признайте, что вопрос ОП является совершенно правильной интерпретацией - возможно, вместе с вашей собственной. Не надо жестких дискуссий.

Спасибо

@justinfagnani

Другой способ взглянуть на это так: если вы импортируете файл .ts, вы импортируете файл, которого не будет после компиляции.

Конечно, не будет, точно так же, как файл .h не распространяется с исполняемым файлом программы C. Именно в этом и суть: вы говорите компилятору включать исходные файлы, а не скомпилированные файлы.

Хорошо, я слишком заспамлен этим разговором, чтобы игнорировать его дальше.
Оператор import НЕ является частью машинописного текста, это часть среды JavaScript, которая его выполнила. Теперь ключевым словом здесь является среда JavaScript , поскольку именно ЭТО разрешает пути. Покажите мне одно приложение, которое во время выполнения импортирует и выполняет файлы .ts (конечно, могут быть и такие, но я бы назвал их хакерскими).
TypeScript позволяет добавлять расширения .js , потому что он позволяет использовать собственный JavaScript внутри своих исходных файлов. ни один из браузеров node.js не будет выполнять файл .ts, даже ts-node транспилирует файлы .ts на лету, просто сохраняет результат в памяти, а не записывает их на жесткий диск (совсем не хакерский ?).

Теперь правильным исправлением tsc будет:

  • у нас есть файл .ts
  • мы ссылаемся на него в другом файле
  • tsc преобразует этот файл .ts в файл .js
  • Затем tsc перезаписывает все прямые ссылки на файл .ts с файлом .js (он точно знает, как он транспилируется, поэтому может правильно его обновить)

Проблема: «современный веб-разработчик» не является настоящим веб-разработчиком и использует способ импорта node.js, пропуская расширение (и весь путь к файлу). tsc теперь больше не знает, что будет на выходе, потому что импорт my-awesome-module/test может быть чем угодно, начиная с файла test.js в node-modules/my-awesome-module через файл index.js внутри папки test в node-modules/my-awesome-module , заканчивающейся некоторыми локальными перезаписями с файлами, отличными от js, такими как ./local-mocks/my-awesome-module/mock.json .

Вот здесь и возникает проблема: как tsc может узнать, что такое причудливая конфигурация webpack/rollup/super-awesome-new-and-shiny-bundler для вашего конкретного проекта?

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

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

Как бы вы сделали это в простом проекте без веб-пакета, я имею в виду только с tsc?

Я читаю все комментарии, и кажется, что это фундаментальное несогласие с ожиданиями использования машинописного текста здесь.

Когда исходные файлы .ts ссылаются на файлы .js, проблема уже началась.

Typescript был создан для ~запуска~ компиляции исходных файлов .ts, а не файлов .js. Если разработчик хочет использовать TypeScript в своем проекте, он должен преобразовать свой _весь_ проект в машинописный текст, а не оставлять потерянные файлы .js и пытаться ссылаться на них. И если у вас нет времени, чтобы изменить содержимое файлов js на синтаксис Typescript, просто переименуйте файлы js в файлы ts (или используйте сопоставление путей TS для сопоставления импорта с файлами .js). Задача решена. :man_пожимая плечами:

РЕДАКТИРОВАТЬ: исправлено «запустить» на «скомпилировать», что я и имел в виду, но я вижу, как это могло быть истолковано по-разному.

@ mkay581 TypeScript никогда не предназначался для запуска чего-либо, только для вывода файлов JS.

@valeriob Простой проект, вероятно, будет иметь не более нескольких файлов, которые не нужно объединять. Браузеры в настоящее время имеют встроенный импорт, и нет необходимости обходить это. Тогда это было бы так же просто, как прослушивание событий навигации в браузере, затем сопоставление каждого события с соответствующим маршрутом, каждый маршрут мог бы импортировать данные с помощью fetch и после возврата мог быть обработан с помощью некомпилированных механизмов шаблонов (буквально html, HyperHTML или более старые, такие как Mustache, Handlebars, Pug и т. д.). Готово, не нужно причудливых веб-пакетов, фреймворков или каких-либо служебных библиотек, только даже слушатели, регулярное выражение, выборка, промисы и простой механизм шаблонов js.

Спасибо @Draccoz , не могли бы вы рассказать мне, как заставить этот простой сценарий работать? https://github.com/valeriob/Typescript_Non_SPA
Это простой файл .ts, ссылающийся на библиотеку JS (например, rxjs), и я хочу использовать его как модуль на странице html.

@valeriob Это не так тривиально, как должно быть. Большинство сторонних библиотек, даже когда они заявляют, что совместимы с модулями ES, не входят в мир браузеров.
RxJS — это то, что меня больше всего интересовало, когда я переносил его в нативный поток, но они ждут, пока этот билет будет разрешен, прежде чем решить реализовать его самостоятельно (забавно…).
В архитектуре, которую я разрабатывал, я сначала использовал sed для исправления всего импорта, но затем передумал использовать простой сервер разработки с перезаписью пути. Моя концепция заключается в том, чтобы в моих приложениях не было внешних зависимостей, кроме rxjs, typescript и lit-html (node_modules с 4 папками и УЛЬТРА быстрыми тестами/сборками CI). Если бы TS переписал пути, это устранило бы необходимость в моем сервере, хотя в любом случае это около 90 строк кода. Это с открытым исходным кодом, если кому-то нужна ссылка, просто спросите или проверьте организации в моем профиле.

Что касается простых страниц, я имел в виду те, которые на самом деле не нуждаются в какой-либо библиотеке, например, переход по URL-адресу -> получение данных -> их отображение -> повторение.

Отсутствие необходимости в использовании какой-либо библиотеки в Js — чистая фантазия, поскольку в Js нет базовой библиотеки.

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

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

Объяснение того, что это _не должно быть проблемой_, не _решает проблему_. Программное обеспечение должно соответствовать ментальным моделям пользователей, а не навязывать пользователям свою собственную модель реализации. (UX-вещи)

Если пользователи концептуализируют tsc как Си-подобный компилятор, согласно @borfast , то это привилегированный ментальный режим, который необходимо учитывать, несмотря на детали реализации tsc.

У вопроса ОП более 200 положительных отзывов, больше, чем у всех других вопросов в репо.

Этот вопрос заслуживает голосования сообщества. Пожалуйста, рассмотрите возможность запуска опроса.

Если большинство пользователей хотят, чтобы tsc переписал их импорт, то это правильный ответ. По крайней мере, это взгляд на вещи с точки зрения UX.

Это еще проще, если машинописный язык как язык является надмножеством JavaScript, вывод tsc (даже не одиночный переключатель выходного файла) должен быть удобочитаемым самим JavaScript.

@weoreference , если вы четко определяете (не пишете код, а просто проектируете), как ТОЧНО следует переписывать пути, учитывая несколько сред (node.js, браузер), возможности нескольких конфигураций сборщика (исследуя все текущие, запланированные и возможные будущие функции webpack, rollup, package и любые другие упаковщики), тогда конечно, тогда, я думаю, команда TypeScript будет на вашей стороне.

Если вы не хотите этого делать или считаете, что это слишком сложно, перестаньте просить их создать функцию, которую никто не может описать, это что-то вроде «мне все равно, как, но заставьте эту корову летать»…

@Draccoz , вы хотите, чтобы ваша машина переключала передачи, чтобы вы могли ездить на ней быстрее 10 км / ч, но я уверен, что производитель никогда не просил вас узнать, как работает зубчатая передача, не говоря уже о ее разработке.

Что касается вопроса о сборщиках и еще много чего, почему это блокировщик для этого?

Послушайте, я просто хочу использовать модули ES, я не хочу иметь дело со всем безумием Babel и Webpack. Почему это не может быть дополнительным параметром компилятора, который просто меняет расширение файла на .js? Если это поведение противоречит другим параметрам конфигурации, установленным пользователем, оно должно быть автоматически отключено или должно отображаться предупреждение/ошибка, а компиляция останавливается при выполнении tsc, чтобы пользователь знал, что ему необходимо изменить конфигурацию.

Я действительно не понимаю, почему это невозможно.

@Draccoz Привет :) Ну, как я понимаю, вы спрашиваете о двух вещах:

  1. Как это можно реализовать

  2. Как я, разработчик, могу сообщить tsc, что я хочу переименовать импорт определенным образом для моей конкретной среды

Вот мои мысли.

  1. См . ответ @borfast ; это ответ «высшего порядка», но краткий :)

  2. Может быть, я могу передать флаг в tsc/tsconfig, например, «renameImports»:true, или какой-то другой сигнал, который получает tsc. Если требуется большая точность, то, возможно, флаг не должен быть логическим, а должен принимать строку, возможно, что-то вроде этого:

стандартное расширение импорта: 'js'

поэтому все импорты без расширений файлов по умолчанию имеют значение .js.

Заключение:
Эта функциональность кажется трудной для реализации только потому, что вы предполагаете, что Q2 (схема переименования импорта) должен быть известен заранее Q1 (т.е. tsc). Но на самом деле нет. Я, разработчик-человек, могу легко передать это «мировое знание» tsc без необходимости знать, как работают веб-пакеты, браузеры и т. д. Все это с простым флагом.

Пользователь не спрашивал @borfast о передаче, она была предоставлена ​​производителем вместе с автомобилем, пользователь просто согласился с тем, что это новая функция, и начал ее использовать - извините, это неверный аргумент. По сравнению с вашим примером пользователя-производителя автомобиля, это больше похоже на «Я хочу, чтобы моя машина была полностью электрическим автомобилем с запасом хода в 100 тысяч миль и максимальной скоростью, достигающей скорости реактивного самолета. Мне все равно, как этого достичь, я хочу это и вот и все - точка.
@weoreference немного неправильно понял мои вопросы. Я спрашивал о том: как заставить tsc понять, на что указывает путь? Это файл js напрямую? Или это папка с index.ts внутри? Или это модуль с package.json, который содержит поле main ? Или следующее поле? Или любой другой, нестандартный? Или это путь, который перезаписывается вебпаком? Или свернуть? Если да, то где конфиг? Может это другой сборщик? Какие-то менее известные? И какие другие варианты использования я не учел в приведенном выше предложении?

Может быть, я могу передать флаг в tsc/tsconfig, например, «renameImports»:true, или какой-то другой сигнал, который получает tsc.

@weoreference , не могли бы вы уже сделать это с сопоставлением путей ? Параметр paths в файле TSconfig дает нам возможность сопоставлять пути импорта с файлами JS. Извините, если неправильно интерпретирую.

@Draccoz Спасибо за ваш ответ, пожалуйста, позвольте мне уточнить

И какие другие варианты использования я не учел в приведенном выше предложении?

О да, для tsc было бы очень сложно знать обо всех этих комбинациях инструментов среды/сборки.

Но у tsc может быть простая утилита, которая поможет разработчикам охватить _большинство_ вариантов использования, и это значение конфигурации «standardImportExtension», которое я объяснил.

Конечно, здесь возникает проблема «гарантии». Ранее в этой ветке утверждалось, что tsc должен «гарантировать», что скомпилированный js действительно будет работать [в некоторой среде].

Ну... может быть, это было слишком тяжелое обязательство. Действительно, tsc очень сложно гарантировать, что js будет работать [в какой-то среде], потому что, как вы только что описали, эту среду очень сложно определить в текущей среде js.

Но простая утилита флага, предложенная @borfast , решает _большинство_ ошибок импорта js, с которыми сталкиваются новые пользователи, пытающиеся использовать tsc.

Расширенное использование, которое, как вы упомянули, состоит во всех этих соображениях —

Это файл js напрямую? Или это папка с index.ts внутри? Или это модуль с package.json, который содержит основное поле? Или следующее поле? Или любой другой, нестандартный? Или это путь, который перезаписывается вебпаком? Или свернуть? Если да, то где конфиг? Может это другой сборщик?

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

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

И самый простой случай — добавить в импорт расширение .js; которые мы можем решить и должны решить.

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

@weoreference посмотрите в самом начале этого разговора, на комментарии @DanielRosenwasser . Он объясняет, почему они не будут его реализовывать («на данный момент»? бесполезная надежда). После его заявления никто из машинописного текста больше не комментировал тему. Для меня эта дискуссия должна быть закрыта, и Microsoft должна официально заявить о своей позиции. Период.
Просто в качестве примечания - лично я полностью за эту функцию, она бы НАМНОГО упростила. Я потерял надежду, потому что я также понимаю аргументы команды машинописи.

@weoreference

Не гипотетически, tsc знает, что сгенерирует его. Он гарантированно существует при использовании tsc.

Но здесь подразумевается симметрия, которую вы не признаете.

Эта «гарантия», которую вы упомянули, действительна в обоих случаях. Если, как вы говорите, «tsc знает, что будет генерировать [файлы js]», то в равной степени уместно задать вопрос: «Ну, тогда почему tsc НЕ действует в соответствии с этой гарантией и не применяет расширения .js, которые, как она знает, отсутствует в скомпилированном js?»

На самом деле симметрия не выполняется. Это не так просто, как просто «применить расширение .js» — tsc должен будет разрешить и переписать спецификатор, а разрешение может зависеть от объявлений типа. TypeScript и Babel поддерживают одномодульные режимы компиляции (isolatedModules для tsc), и в этом случае, если вы импортируете типы вместо JavaScript, tsc должен будет загрузить объявления типов, чтобы определить, где будет находиться соответствующий файл .js, чтобы переписать спецификатор. Чтобы обеспечить согласованность и избежать крайних случаев, проще всего поддерживать импорт только тех файлов .js, которые существуют до компиляции или являются известным результатом текущего проекта.

@justinfagnani @Draccoz Спасибо; хорошо, да я понимаю.

Мой последний комментарий: «Только то, что сложные случаи не могут быть решены, не означает, что мы не можем решить простые случаи».

Спасибо

Я предполагал, что TypeScript здесь противоречит спецификации (и создает недопустимый JavaScript), но я не могу найти нигде в спецификации , где действительно требуется, чтобы путь импорта точно соответствовал именам файлов (с расширением). Это очень сложно переварить, поэтому я не совсем уверен, но все, что я могу найти, это то, что спецификация требует, чтобы «ModuleSpecifier» в «FromClause» был «StringLiteral». Кажется очень расплывчатым определением, но я полагаю, что это может быть сделано для обеспечения гибкости в разрешении модулей во многих различных средах, в которых существует ECMAScript. Кто-нибудь может подтвердить, правильно ли я это читаю? Если это действительно так, мне придется смягчить свою позицию в отношении того, как TypeScript обрабатывает это. Хотя я все же предпочел бы, чтобы между TypeScript, Node и сетью было больше возможностей взаимодействия. Нынешняя ситуация не идеальна.

Я пришел к этому вопросу после прочтения этого . Эта проблема создала у меня впечатление, что система Node работает так, как она работает (строго совпадающие имена файлов) из-за спецификации ES, но теперь я вижу, что неправильно понял это (они не ссылались на спецификацию ES), и, возможно, ни Node, ни TypeScript на самом деле не делают ничего «неправильного». Тогда эта проблема действительно связана с несовместимостью между одинаково допустимыми подходами к разрешению модулей в разных средах. Тем не менее, очевидно, что основными целевыми средами для TypeScript являются Node и Интернет, и хотя Node теоретически может изменить свой подход, я не думаю, что это очень вероятно для браузеров, поэтому я по-прежнему считаю, что этот вопрос актуален.

Изменить: я думаю, что это может быть этот раздел спецификации , который, кажется, указывает, что разрешение модуля «определяется хостом»?

@kj соответствующий текст спецификации находится в спецификации HTML: https://html.spec.whatwg.org/multipage/webappapis.html#resolve -a-module-specifier

В нем говорится, что спецификаторы импорта должны быть полными URL-адресами или абсолютными или относительными путями. Если спецификатор не анализируется как URL-адрес (обычно начинается с http:// или https:// ) или начинается с / , ./ или ../ выдается ошибка. Спецификаторы пути разрешаются относительно базового URL-адреса импортера.

Никакой другой поиск или разрешение пути не выполняется. Это означает, что спецификатор должен разрешаться в полный URL-адрес модуля, и вы должны включить расширение, если оно требуется серверу. У серверов есть возможность возвращать ответы для URL-адресов без расширения.

Причина, по которой Node использует более строгий алгоритм разрешения для модулей, заключается в большей совместимости с Интернетом, поэтому чаще всего модули, опубликованные в npm, не нуждаются в дополнительных инструментах для запуска в браузерах. Импорт по имени пакета по-прежнему является очень важной функцией, поэтому Node поддерживает это, но стремится быть совместимым с предложением Import Maps (которое Deno и SystemJS уже поддерживают).

В общем, поддержка tsc для импорта с расширениями .js отлично работает как в Node, так и в веб-браузерах. На самом деле импорт без расширений вызывает проблемы без дополнительных инструментов. Однако обычно инструменты, поддерживающие разрешение узла для имен пакетов, также используют разрешение стиля класса require() и разрешают относительные пути, а также добавляют свои расширения. Вот что делает es-dev-server .

Спасибо @justinfagnani. Так что, по крайней мере, в браузере все зависит от того, как это реализует сервер. Это хорошо знать. Это все еще довольно неинтуитивно и сбивает с толку, и я считаю, что необходимо больше сближения между проектами на благо сообщества, но я больше не уверен, как это может выглядеть.

Изменить: на данный момент мне этого будет достаточно (особенно с учетом приведенных выше объяснений, мне так удобнее):

https://nodejs.org/api/esm.html#esm_customizing_esm_specifier_resolution_algorithm

Я не уверен, упоминается ли этот параметр в документации по TypeScript, но если нет, возможно, это следует сделать, чтобы избежать путаницы. Похоже, это не так, ищите либо « site:typescriptlang.org specifier-resolution», либо « site:staging-typescript.org specifier-resolution». Хотя, поскольку это все еще довольно новое в Node, это не так уж удивительно.

@justinfagnani Я согласен с тем, что расширение .js просто работает в большинстве случаев, за исключением случаев, когда кто-то занимает идеологическую позицию _против_ этого (например, https://github.com/TypeStrong/ts-node/issues/783, с которым вы знакомы).

Я сделал версию скрипта @quantuminformation без зависимостей здесь . Эта версия также содержит регулярное выражение, которое заменяет только те модули, которые уже не заканчиваются на .js .

такая же потребность

Достижение расширений .js для совместимости с ESM с помощью .js в операторах импорта у меня не работает. Когда я импортирую файл TS и опускаю любое расширение, он компилируется нормально. Когда я добавляю расширение .js в импорт, я получаю много ошибок (которых не должно быть) от компилятора TS.

Кажется, основная причина того, что эта функция не разрабатывается, связана со сложностью/невозможностью совместимости с различными сборщиками, но Node.js и сборщики разработали свои собственные схемы модулей в отсутствие поддержки модулей в ECMAScript. Теперь, когда у нас есть ESM, какой бы неадекватной она ни казалась некоторым людям, это путь вперед. По мере разработки большего количества кода в ESM и веб-компонентах использование упаковщиков будет уменьшаться, и эта болевая точка между TS и ESM вызовет больше трений. Было бы хорошо, даже если первоначальная поддержка глючит и не рассматривает все варианты использования, если бы ее можно было начать поддерживать.

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

настроить в вашем package.json:

  ..
    "scripts": {
        "build": "node build.js",
   ...

//build.js
import { execSync} from "child_process"
import * as util from "util"
import * as fs from "fs"
import * as path from "path"

//function to recurse dirs finding files
function fromDir(startPath, filter, callback) {

    //console.log('Starting from dir '+startPath+'/');

    if (!fs.existsSync(startPath)) {
        console.log("no dir ", startPath);
        return;
    }

    var files = fs.readdirSync(startPath);
    for (var i = 0; i < files.length; i++) {
        var filename = path.join(startPath, files[i]);
        var stat = fs.lstatSync(filename);
        if (stat.isDirectory()) {
            fromDir(filename, filter, callback); //recurse
        }
        else if (filter.test(filename)) callback(filename);
    };
};

//this add .js to lines like:  import .* from "\.  <-- only imports from ./ or ../ are touched
function addDotJsToLocalImports(filename) {
    var buf = fs.readFileSync(filename);
    let replaced = buf.toString().replace(/(import .* from\s+['"])(?!.*\.js['"])(\..*?)(?=['"])/g, '$1$2.js')
    if (replaced !== buf.toString()) {
        fs.writeFileSync(filename, replaced)
        console.log("fixed imports at "+filename )
    }
}

//------------------------
//---BUILD TASK START 
//------------------------

execSync("npx tsc --build -verbose", { stdio: 'inherit' })

//add .js to generated imports so tsconfig.json module:"ES2020" works with node
//see: https://github.com/microsoft/TypeScript/issues/16577
fromDir("./dist", /\.js$/, addDotJsToLocalImports)

на основе https://github.com/microsoft/TypeScript/issues/16577#issuecomment -310426634

Кто-нибудь может вспомнить, что они делали 3 года назад, когда этот вопрос был открыт?

Решение, не связанное с пакетированием, заключается в написании проектов, распространяемых через Интернет, с расширением .js .

Это 100% работает. Большая проблема заключается в попытке написать модули, ориентированные на веб и Node.js, но это проблема для JS в целом.

Если бы что-то нужно было сделать, это добавило бы --moduleResolution=web , но это не входит в рамки этого вопроса.

Мне пришлось написать этот скрипт после сборки, чтобы добавить расширение .js.

fix-ts-imports

#!/usr/bin/env sh

# Fixes JavaScript module imports generated by TypeScript without extension.
# Converts
# import {} from './module'
# into
# import {} from './module.js'
#
# EXAMPLE
# ./fix-ts-imports

ProjectDir="$(cd "$(dirname "$0")/.." && pwd)"

fix() {(
        local pkg="$1"
        shift

        find "$pkg" -type f -iname '*.js' -not -ipath '*/node_modules/*' -print0 \
        | while read -r -d '' file; do
                sed -i '' -E 's|(import .+ from ['\''"]\.?\./.+[^.][^j][^s])(['\''"])|\1.js\2|g' "$file"
        done
)}

if test $# -eq 0; then
        set -- "$ProjectDir"
fi

for pkg; do
        fix "$pkg"
done

У меня есть аналогичный скрипт в JavaScript:
https://github.com/yoursunny/NDNts/blob/743644226fe18d48e599181e87ad571a2708a773/mk/build-post.js

Он вызывается как:

tsc -b mk/tsconfig-solution.json -w --listEmittedFiles \
  | node mk/build-post.js

Основным недостатком скриптов такого типа является то, что они нарушают исходные карты, поэтому отладка становится менее эффективной.

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

  • машинопись
  • модули
  • свернуть

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

— видимо вебпак виноват...

А так — кот вылез из мешка.

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

_Большинство_ работает превосходно, и я согласен с тем, что все исходные файлы должны иметь расширения .js при экспорте. По моему опыту, единственная вещь, которая плохо работает с этим, — это ts-node из-за их упорного отказа поддерживать расширения .js . Да, вы можете добавить этап предварительной транспиляции перед запуском узла, и импорт .js будет работать, но если вы хотите запустить код .ts или тесты непосредственно с узлом, а также в браузере, вам в настоящее время в основном не повезло. (Чтобы уточнить, я думаю, что это ошибка ts-node, а не ошибка TypeScript).

Спасибо @chase-moskal.

Я реорганизовал репозиторий и файл tsconfig, и теперь
import {something} from './something.js'
не бросает
typescript force overwrite error TS5055: Cannot write file because it would overwrite input file
больше, и мне больше не нужен хак fix-ts-imports .

В 250+ комментариях было очень мало ясности. Обобщить:

Задний план

Модули браузера

Браузеры разрешают модули EcmaScript в соответствии с URL-адресом, включая относительные URL-адреса. ( ЧТО )

Модули Node.js

Node.js разрешает модули (как EcmaScript, так и CommonJS, специфичный для Node.js) с помощью гораздо более сложного алгоритма, который включает несколько откатов и разбор файлов package.json. ( Node.js ) Это можно настроить, например, с помощью --experimental-specifier-resolution=explicit , для которого требуется полный путь.

Модули TypeScript

TypeScript имеет несколько доступных алгоритмов разрешения модулей и множество опций для их дальнейшей настройки. ( TypeScript ) Цель состоит в том, чтобы пользователи писали те же спецификаторы модулей, которые используются в произведенном выводе, настраивая разрешение tsc с помощью таких параметров, как baseUrl и pathMappings.

На практике большинство пользователей используют узел moduleResolution, ориентируясь на среду Node.js или совместимый упаковщик. Этот запрос ориентирован на пользователей, использующих браузеры без сборщика.

разрешение модуля ts-node

Судя по всему, ts-node не поддерживает идентификаторы модулей с расширениями. Хотя неясно, почему, поскольку и Node.js, и TypeScript работают, а ts-node якобы является их объединением.

Факты

Факт 1: Вы можете использовать расширения .js

Для более широкой совместимости (а именно с браузерами) сегодня вы можете использовать расширения .js. За странным исключением ts-node (ошибка IMO) все работает прямо сейчас, указав полный путь (то есть включая расширение).

Факт 2: Это не так просто, как «добавить расширение»

Этот запрос лучше охарактеризовать как «преобразование идентификатора модуля в путь к файлу». Например, ./example становится ./example/index.js а 'lodash' становится '.node_modules/lodash/index.js' .

Обратите внимание, что иногда нет даже разрешенного пути к файлу, например, в объявлениях внешних модулей.

declare module "lodash" {
}

Возможно, переписывание модулей ограничено модулями TS в текущем проекте/компиляции.

В любом случае, мы сейчас нарушаем один из конструктивных параметров ТС, что другие модули влияют на вывод для текущего.

Заключение

Можно использовать путь для идентификаторов модулей, которые работают для сети. (Например, ./foo/index.js вместо ./foo .)

(Хотя с практической точки зрения вам, скорее всего, понадобится сборщик для целевых браузеров. А именно, если используются пакеты npm.)

@pauldraper есть важная проблема с «Фактом 2»:

Этот запрос лучше охарактеризовать как «преобразование идентификатора модуля в путь к файлу». Например, ./example становится ./example/index.js, а «lodash» становится «node_modules/lodash/index.js».

Вы действительно не хотите разрешать спецификаторы вне вашего пакета во время компиляции, потому что это могут быть недоступные пути, когда пакет установлен где-то еще. Вам необходимо запускать разрешение модуля Node при каждой уникальной установке пакета. В противном случае мы могли бы написать и опубликовать import {} from './node_modules/lodash/index.js' и покончить с этим.

@justinfagnani , я согласен, но это демонстрирует, что идентификаторы модулей абстрактны, и вы манипулируете расположением модулей вне tsc. И что tsc не может/не должен заниматься такими манипуляциями.

Этот запрос лучше охарактеризовать как «преобразование идентификатора модуля в путь к файлу». Например, ./example становится ./example/index.js, а «lodash» становится «.node_modules/lodash/index.js».
Обратите внимание, что иногда нет даже разрешенного пути к файлу, например, в объявлениях внешних модулей.

Это не то, о чем этот запрос. Речь идет о добавлении расширения при генерировании кода. Мы хотим писать модули, совместимые с типом: «модуль» без дополнительного шага хакерской сборки. Внешние модули, такие как lodash, будут продолжать работать даже без .js, поскольку это CommonJ.

Пример:

// ./src/moduleA.ts
export const test = 2;
// ./src/moduleB.ts
import {test} from './moduleA'



md5-ec0300a1c6d92a03c70699d0e52c0072



```js
// ./lib/moduleB.js
import {test} from './moduleA.js'

В дополнение к приведенному выше машинописному тексту не поддерживаются package.json «экспорт» и «тип». В проектах, которыми я руковожу, нет пути к настоящему ESM.

Этот запрос ориентирован на пользователей, использующих браузеры без сборщика.

Это неправильно. Я редко пишу TS/JS для браузеров, я в основном работаю над кодом на стороне сервера, и мне это также нужно, потому что я хочу использовать загрузку ESM в узле и не зависеть от сборщиков и дополнительного кода для загрузки модулей.

Внешние модули, такие как lodash, будут продолжать работать даже без .js, поскольку это CommonJ.

Если только они не.

При испускании.

Это может быть ./moduleA.js . Или это может быть ./moduleA/index.js , верно? Разрешение модуля Node.js допускает несколько путей.

Если только они не.

Можете ли вы привести пример, когда они не будут работать? Node.js только что получил поддержку импорта именованного экспорта из CommonJS.
https://nodejs.org/api/esm.html#esm_import_statements

Это может быть ./moduleA.js. Или это может быть ./moduleA/index.js, верно? Разрешение модуля Node.js допускает несколько путей.

Не в режиме ЕСМ. index.js больше не будет поддерживаться, как сейчас. Загрузчик ESM будет читать метаданные package.json «экспорт» и «тип».
https://nodejs.org/api/esm.html#esm_mandatory_file_extensions

Для проектов на основе машинописного текста + node.js нам нужна лучшая собственная история ESM. Это может произойти с помощью инструментов (машинописи) или в node.js. Проблема в том, что нет единого мнения о том, что следует делать.

Отредактируйте удаленную ссылку на узел PR, так как она вводила в заблуждение.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги