microsoft / microsoft/TypeScript
Index type distributes over intersections too eagerly
オープン
まだ誰も着手していません。
Domain: Indexed Access Types
Help Wanted
Possible Improvement
- 主要言語
- Go
- スター
- 111k
- フォーク
- 14.3k
- 平均マージ
- 2日 4時間
- マージ済み PR(30日)
- 132
説明
🔎 Search Terms
index keyof indexed access deferred deferral instantiation
🕗 Version & Regression Information
- This is the behavior in every version I tried
⏯ Playground Link
💻 Code
type Values<T> = T[keyof T];
// transforms from "keyed object map" to a union
type ExtractEventsFromPayloadMap<T> = Values<{
[K in keyof T]: T[K] & { type: K };
}>;
type EnqueueObject<TEmittedEvent extends { type: PropertyKey }> = {
// creates proxy methods
emit: {
[K in TEmittedEvent["type"]]: (
payload: Omit<TEmittedEvent & { type: K }, "type">,
) => void;
};
};
type Exec<TEmitted extends { type: PropertyKey }> = (
enq: EnqueueObject<TEmitted>,
) => void;
declare function createStore<TEmitted>(definition: {
emits: {
[K in keyof TEmitted]: (payload: TEmitted[K]) => void;
};
exec: Exec<ExtractEventsFromPayloadMap<TEmitted>>;
}): any;
createStore({
emits: {
increased: (_: { upBy: number }) => {},
decreased: (_: { downBy: number }) => {},
},
exec: (enq) => {
enq.emit.increased({
upBy: "bazinga", // this should error!
});
const fn = enq.emit.increased;
// ^?
// this is just a copy of what is displayed as `enq.emit.increased`'s type
const exactSameTypeAsAbove: (
payload: Omit<
{ upBy: number } & { type: "increased" } & { type: "increased" },
"type"
>,
) => void = () => {};
exactSameTypeAsAbove({
upBy: "bazinga", // this one errors correctly
});
},
});
🙁 Actual behavior
There is no error on the annotated call
🙂 Expected behavior
It should error
Additional information about the issue
keyof (T & { type: K })gets normalized tokeyof T & "type"- that passed through
Exclude<X, "type">(withinOmit) is left asExclude<keyof T, "type">. - then
Tgets instantiated withExtractEventsFromPayloadMap<{ increased: { upBy: number; }; decreased: { downBy: number; }; } - but now
keyof ...returns only shared keys of this union - the only shared key is
typeso thisExcludegets computed asnever(Exclude<"type", "type">) - and the final parameter type of
enq.emit.increasedgets computed as just{}(from{ [K in never]: ... })
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
リンクされた TypeScript Playground の再現から始め、indexed access、keyof、intersections、Omit に対する checker のパスを追跡します。注釈付きの callback 呼び出しと、同等の関数型を明示的に記述した場合を比較します。推論された enq.emit.increased 呼び出しが upBy に対する string を拒否し、報告されたケースをカバーする回帰テストがあることを完了条件とします。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- typescript
- 領域
- compilers
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 42/100