microsoft / microsoft/TypeScript
Suggestion: Automatically infer argument types in overloaded function implementation
まだ誰も着手していません。
- 主要言語
- Go
- スター
- 111k
- フォーク
- 14.4k
- 平均マージ
- 1日 19時間
- マージ済み PR(30日)
- 117
説明
Search Terms
infer, arguments, function, overload
Suggestion
For basic container types (Point, Size, Rect, ...) I often write constructors and methods with overloaded signatures so they can be called with the container type itself or with the separate components of the container as arguments. Example:
class Point {
constructor(point: Point);
constructor(x: number, y: number);
constructor(arg1: Point | number, arg2?: number) {
if (arg1 instanceof Point) {
this.x = arg1.getX();
this.y = arg1.getY();
} else {
this.x = arg1;
this.y = arg2!;
}
}
}
And I always wonder why I have to specify the argument types in the implementation again when I already defined the possible types in the overload signatures.
In this simple Point type it is still pretty easy but imagine a Rect type which can work with four number arguments, two Point arguments, a Point and Size argument or a Rect argument. Manually writing the combined signature for all these overloaded signatures is cumbersome. And I don't want to use any here because I want type checking in the function body.
An alternative way to write this example is this:
class Point {
constructor(point: Point);
constructor(x: number, y: number);
constructor(...args: [ Point ] | [ number, number ]) {
const [ arg1, arg2 ] = args;
// arg1 is now Point | number
// arg2 is now number | undefined (At least since TS 3.2 because of #27543)
...
}
}
This shows how easy it should be for TypeScript to collect the possible function signatures into a union type so writing constructor(...args) would be enough.
Taking this a step further I even like to write this so I don't need to destructure the arguments myself:
class Point {
constructor(point: Point);
constructor(x: number, y: number);
constructor(arg1, arg2) {
// arg1 is now Point | number
// arg2 is now number | undefined
...
}
}
Taking this ANOTHER step further TypeScript could even narrow down the inferred function signatures by each type check done within the function body:
class Point {
constructor(point: Point);
constructor(x: number, y: number);
constructor(arg1, arg2) {
if (arg1 instanceof Point) {
// arg2 can now only be `undefined` because the instanceof check removes
// the second call signature (where arg1 is a number) from the list of possible
// call signatures
this.x = arg1.getX();
this.y = arg1.getY();
} else {
// arg2 can now only be `number` because the failed instanceof check removes
// the first call signature from the list of possible signatures
this.x = arg1;
this.y = arg2;
}
}
}
I guess the type narrowing is harder to implement but at least the automatic type inference of each argument shouldn't be that hard. So it would be very nice if a future version of TypeScript could do this so using overloading gets a bit easier.
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. new expression-level syntax)
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
この issue ではファイルもテストも指定されていません。まず TypeScript のオーバーロード処理と引数の型推論を追跡し、次に Point の例を現在のコンパイラーの動作と比較してください。オーバーロードの実装が互換性のあるパラメーター型を推論でき、同時に本体内の型チェックと絞り込みを維持できれば完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- typescript
- 領域
- compilers
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 25/100