microsoft / microsoft/TypeScript
Allow importing both type entity and value entity for "const enum" through "import type"
まだ誰も着手していません。
- 主要言語
- Go
- スター
- 111k
- フォーク
- 14.3k
- 平均マージ
- 2日 4時間
- マージ済み PR(30日)
- 132
説明
Search Terms
const enum, import, importsNotUsedAsValues
Scenario
I am a library developer, and there is a really large types.ts file in my project, which contains many interface, type, and const enum, defining a large part of types of the project, just like you do (typescript/src/compiler/types.ts).
Recently I turned on the compiler option importsNotUsedAsValues, and found some problems about const enum.
Original fileA.ts
import {
TypeA, TypeB, TypeC,
ConstEnumD, ConstEnumE,
} from './types.ts';
------------------
Current fileA.ts
import type {
TypeA, TypeB, TypeC,
} from './types.ts';
import {
ConstEnumD, ConstEnumE,
} from './types.ts';
Because the entities of enum belong to both type scope and value scope, I have to import them separately if I want to use them as values.
Now I have to separate the import of type const enum from a lot of names file by file, which is really a lot of work.
What's worse, after turning on importsNotUsedAsValues, TypeSciprt unnecessarily write require('./types.js') into fileA.js though the generated code did not access any property of require('./types.js'). In other words, it makes types.ts seems to have side effects. And this feature may affect the file reference relation of the project and lead to incorrect Rollup order.
In my mind, accessing the const enum entity in value scope is a kind of special behavior and is something that will be replaced in compile-time. There should be a way to import both type entity and value entity of const enum from a file without really requiring the file, especially when the file really has side effects.
Solution
There are 2 ways to solve this problem:
1. import both type and value for const enum through import type
import type { ConstEnumA } from './types';
// Type↓ Value↓
const a: ConstEnumA = ConstEnumA.propA;
// ts not emit " require('./types') "
I prefer this method because I will not need to greatly change my code.
Breaking change?
Name conflicts may occur if there was already a name in value scope which was same with 'ConstEnumA',
but I think this is very very rare and will be prevented by linter usually. An extra compiler option can be provided to solve this.
2. check const enum in value-import
// importsNotUsedAsValues is still on
import { ConstEnumA } from './types';
// Type↓ Value↓
const a: ConstEnumA = ConstEnumA.propA;
// ts find just "ConstEnumA" is used and it is `const enum`
// not emit " require('./types') "
Breaking change?
Yes. Now TS do not emit require('...') though value-import exists in the code.
Examples
A complete example of Solution 1:
import type {
TypeA,
TypeB,
TypeC,
ConstEnumA,
TypeD,
TypeE,
TypeF,
ConstEnumB,
TypeG,
TypeH,
TypeI,
ConstEnumC,
ConstEnumD,
TypeJ,
TypeK,
} from './types';
const b: ConstEnumB = ConstEnumB.propA;
// compiler: OK, 0 error(s). not emit " require('./types.js') "
Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
Issue にある fileA.ts と types.ts の例、およびそこで説明されている importsNotUsedAsValues の動作から始めます。提案されている 2 つの解決策を比較し、選択した設計によって import type を通じた const enum の型としての使用と値としての使用が、require('./types.js') を出力せずに可能になることを確認します。同時に、既存の JavaScript の動作も維持します。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- typescript
- 領域
- compilers
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 停滞
- 明瞭さ
- 明確に書かれている
- 初心者へのやさしさ
- 35/100