microsoft / microsoft/TypeScript
Need a dummy overload to improve inference
まだ誰も着手していません。
- 主要言語
- Go
- スター
- 111k
- フォーク
- 14.4k
- 平均マージ
- 1日 19時間
- マージ済み PR(30日)
- 117
説明
TypeScript Version: 3.x, 4.0.0-beta, nightly
Search Terms: dummy fake overload infer
Code
class FieldEvent<T extends Field> {
constructor(readonly field: T, readonly message: string) { }
}
class Field {
listen<T extends FieldEvent<Field>>(type: new (...args: any[]) => T, listener: (event: T) => void): void { }
}
class BeforeSetEvent<T extends number | string> extends FieldEvent<ValueField<T>> {
constructor(field: ValueField<T>, public newValue: T) { super(field, ""); }
}
class AfterSetEvent<T extends number | string> extends FieldEvent<ValueField<T>> {
constructor(field: ValueField<T>, readonly oldValue: T) { super(field, ""); }
}
class ValueField<T extends number | string> extends Field {
constructor(public value: T) { super(); }
// listen<U extends FieldEvent<Field>>(type: new (arg: this) => U, listener: (event: U) => void): void;
// listen<U extends FieldEvent<Field>>(type: new (...args: any[]) => U, listener: (event: U) => void): void;
listen<U extends FieldEvent<Field>>(type: new (...args: any[]) => U, listener: (event: U) => void): void {
super.listen(type, listener);
}
}
let field = new ValueField(0);
field.listen(FieldEvent, (event) => event.field); // event: FieldEvent<any>
field.listen(BeforeSetEvent, (event) => { event.field; event.newValue; }); // event: BeforeSetEvent<any>
field.listen(AfterSetEvent, (event) => { event.field; event.oldValue; }); // event: AfterSetEvent<any>
Expected behavior:
event to be better inferred than any.
Actual behavior:
event inferred as any.
But if we uncomment the 2 overloads, then event is correctly inferred:
field.listen(FieldEvent, (event) => event.field); // event: FieldEvent<ValueField<0>>
field.listen(BeforeSetEvent, (event) => { event.field; event.newValue; }); // event: BeforeSetEvent<0>
field.listen(AfterSetEvent, (event) => { event.field; event.oldValue; }); // event: AfterSetEvent<0>
What's surprising (so the reason I consider it as a bug):
- The 1st overload doesn't match any signature.
- But it influences the way the other overload is inferred.
Note that if we replace (arg: this) by () or another type, then:
field.listen(FieldEvent, (event) => event.field); // event: FieldEvent<Field>
field.listen(BeforeSetEvent, (event) => { event.field; event.newValue; }); // event: BeforeSetEvent<string | number>
field.listen(AfterSetEvent, (event) => { event.field; event.oldValue; }); // event: AfterSetEvent<string | number>
Playground Link: Playground Link
Related Issues: I first posted #36226 but was not able to solve my issue, until I found the (arg: this) trick.
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
リンク先の TypeScript Playground の例をまず再現し、2 つのオーバーロードがある場合とない場合で推論を比較します。listen 呼び出しに対するコンパイラのジェネリック推論とオーバーロード解決の動作を追跡します。ダミーのオーバーロードなしで、コールバックから FieldEvent、BeforeSetEvent、AfterSetEvent が関連する具体的な型とともに推論されれば完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- typescript
- 領域
- compilers
- issue の種類
- バグ
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 25/100