microsoft / microsoft/TypeScript

Feature Request: Make "loaders" a first class citizen of the language

オープン
#16,170 コメント 7 件 リアクション 7 件 担当者 1 名 GitHub で見る

@rbuckton がすでに取り組んでいます。

2019年8月23日 から。

Needs Investigation
主要言語
Go
スター
111k
フォーク
14.4k
平均マージ
1日 19時間
マージ済み PR(30日)
117

説明

This follows some thoughts I had with "The Maybe Future of Frontend Tooling" and picks up some use cases which aren't covered by the current (awesome!) language server plugin support as far as I know. I also created https://github.com/Microsoft/TypeScript/issues/15589 which refers to linter rules. This issue is about loaders - in the sense how they were introduced by webpack.

In general both issues - this one and https://github.com/Microsoft/TypeScript/issues/15589 - remind me of Cheng Lous talks about "Taming the Meta Language" and "What's in a language?". Linters and loader are not a part of the current language in a strict sense, but part of our meta language and it is good to formalize more of them so they become a language construct. (Part of Cheng Lous talks is about why reason for example doesn't have a separate linter.)

Current state

  • Loaders like they are used by webpack allows us to require non JavaScript files (or non TypeScript files) and transform them into a JavaScript/TypeScript "file" or require JavaScript/TypeScript files and transform them so they'll have a different interface.

  • TypeScript supports loaders in two ways:

    • Either write an interface for them directly (e.g. declare module 'foo-loader?param=bar!../test';).
    • Or use a wild card (e.g. declare module 'foo-loader?*).
  • This is either cumbersome/error prone and/or limited, because they interfaces can't be typed in a very dynamic way.

  • Two use cases which we currently have, which I'd like to point out:

Use case 1

We have translations in a file called en.properties (and other files for other languages) which could look like this:

say-something={gender, select, f {She} m {He}} is great.

I'd like to import this file as import { saySomething } from '../i18n/en.properties'; which would have an interface like this:

declare module '../i18n/en.properties' {
  /**
   * `en`: {gender, select, f {She} m {He}} is great.
   * `de`: {gender, select, f {Sie} m {Er}} ist toll.
   */
  export function saySomething(data: { gender: 'f' | 'm' }): string;
}

We currently need to pre-compile our translations and emit a .d.ts and a .js, so we import the .js instead of the .proprties. Only then we get this complex interface.

Use case 2

We add new exported functions to existing modules so we can mock them easily. What will be added depends on the query parameters of the loader. It could look like this: 'import-inject-loader?fetch!../src/get-users'.

E.g. using import-inject-loader?fetch will add two new exported functions to ../src/get-users: ilOverwriteFetch and ilResetAll.

Currently we need declare every module which uses import-inject-loader as any (declare module 'import-inject-loader?*';). Everything else would be too hard to maintain.

What I'd like to see

  • I would like to get proper typings for imported files where the content changes the interface (= use case 1) without precompiling, but with importing the file directly.

  • I would like to get proper typings for files with existing interfaces, but which are transformed (in the easiest case just extended) into a different interface without loosing the original interface (= use case 2).

  • I would like to get proper typings for imported modules, when the interface changes, because of loader options (= use case 2).

  • I would like to get assistance when configuring loaders through query parameters (= use case 2, e.g. show an error, when I write 'import-inject-loader?fetch!../src/get-users', if there is no fetch used inside ../src/get-users).


If something like that isn't in the scope of a TypeScript core team, I could think of giving a new "TypeScript tooling team" this scope which develops closely together with the TypeScript core team in a similar fashion like the VS code team.

I think it is important to address these meta language issues somehow in an official way to get a nice TypeScript ecosystem.

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

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

はじめの一歩

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

評価

この issue はまだ評価されていません。

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

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