microsoft / microsoft/TypeScript

Alternative to rewriteRelativeImportExtensions & allowImportingTsExtensions

オープン
#61,050 コメント 2 件 リアクション 2 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

Awaiting More Feedback Suggestion
主要言語
Go
スター
111k
フォーク
14.3k
平均マージ
2日 4時間
マージ済み PR(30日)
132

説明

🔍 Search Terms

"rewriteRelativeImportExtensions", "allowImportingTsExtensions", "extension', "rewrite", "tsc"

✅ Viability Checklist
⭐ Suggestion

Although the recent rewriteRelativeImportExtensions tsc option is a big step forward with the more and more needed feature of rewriting .ts extensions to .js when compiling with tsc, it suffers of some drawbacks (may emit shims, false-positives, developer de-responsabilisation, ...) and limitations imposed by the very reasonable Typescript design goals or other things well described by Ryan Cavanaugh in https://github.com/microsoft/TypeScript/issues/49083#issuecomment-1435399267.
The older option allowImportingTsExtensions is, for its part, a workaround to permit run-in-place usages (directly executing TS sources, with no compilation, as if it was a JS file), that didn't exist at the TS creation time.

Today, I want to propose a solution way more generic I never seen before in any conversations around these features/needs. What is complex and incertain for the compiler here? Something very trivial for a human: determining which string literals (please note: "string literals") in the TS source code are paths pointing to TS files that, once built, will point to JS files. Really transforming such strings is not a big deal, but determining which ones is, because it may depends on a huge amount of configurations, alias, module resolver and other wild things. So, if it's so simple for a human, why not asking him/her to bring this knowledge to the compiler?

So, here is the // @ts-rewrite-ts-extension comment (the name doesn't matter at this point, and my English is definitely improvable). The main and unique goal of it, is indicating to tsc that it should transform the nearby literal string ending with .ts to .js before doing any treatments on this string (also for other members of this family: .tsx, .mts, or .cts to their "j" counterpart). Why I keep talking about string literals and not about paths? Because it absolutely doesn't matter and will permit the developer to handle its own cases, even dynamic imports, explicitly and with no runtime shim.
An indirect consequence is, if this transformation occurs before the allowImportingTsExtensions: false check (TS5097) in the tsc process, this option doesn't need to be turned on anymore to allow importing .ts extensions, as they will be seen as .js (and valid) by this check. It's totally in the spirit of the TS5097 error to forbid clearly invalid paths and to allow those possibly valid once built.

This idea is now yours, improve and refine it or maybe even throw it away. 🙂

📃 Motivating Example

ESM import (or export from):

// two lines form
// @ts-rewrite-ts-extension
import * from './foo.ts';

// single line
import * from './foo.ts'; // @ts-rewrite-ts-extension

CJS require:

const lib = require('./foo.ts'); // @ts-rewrite-ts-extension

ESM functional import():

const dynamic = await import('./foo.ts'); // @ts-rewrite-ts-extension


// with a simple string
const filepath = './foo.ts'; // @ts-rewrite-ts-extension
...
const dynamic = await import(filepath);


// with a constructed string
let filepath = BASE_PATH;
...
filepath += 'foo.ts'; // @ts-rewrite-ts-extension
...
const dynamic = await import(filepath);

Why not a block form in which all string literals will be transformed?

// @ts-rewrite-ts-extension-begin
import * from './foo1.ts';
import * from './foo2.ts';
import * from './foo3.ts';
// @ts-rewrite-ts-extension-end

No matter the reason why the developer wants to rewrite the extension, any eligible literal can be transformed:

// module specifier
import * from '#blah/foo.ts'; // @ts-rewrite-ts-extension

// really anything
console.log('./foo.ts'); // @ts-rewrite-ts-extension
💻 Use Cases
  1. What do you want to use this for?
    Creating TS projects that can run-in-place in Node, but also buildable with tsc and distributed as npm packets, with a unique code base.

  2. What shortcomings exist with current approaches?
    See the suggestion block

  3. What workarounds are you using in the meantime?
    tsx because it doesn't impose the Node Typescript restriction on extensions, and more recently tried rewriteRelativeImportExtensions.

  4. Other improvements around this proposition:

  • When used on non-eligible string literals, i.e. a string not ending by a .ts extension, an error may be emitted by tsc, because it's a clear mistake. Bad usage example:
// Error TSXXXX: Why the hell you want to transform an inexistant .ts extension?
import * from './foo.js'; // @ts-rewrite-ts-extension
  • When used on lines with multiple string literals, an error may also be thrown to avoid any ambiguities.
// Error TSXXXX: Ambiguous @ts-rewrite-ts-extension usage, multiple strings can be affected
console.log('bar', './foo.ts'); // @ts-rewrite-ts-extension

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

この提案は、tsc による rewriteRelativeImportExtensions、allowImportingTsExtensions、文字列リテラル、コメントディレクティブの処理に関するものです。まず、これらのオプションと TS5097 に対応するコンパイラの経路を確認し、次に、要求されたディレクティブが imports、require、dynamic import、通常の文字列とどのように相互作用するかを判断してください。完了条件は、合意された設計と、列挙された拡張子およびディレクティブ形式に対するカバレッジがあることです。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
typescript
領域
compilers
issue の種類
機能追加
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
説明が足りない
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。