Microsoft/TypeScript
Vedi su GitHubIndex type distributes over intersections too eagerly
Open
#61.101 aperta il 2 feb 2025
Domain: Indexed Access TypesHelp WantedPossible Improvement
Metriche repository
- Star
- (48.455 star)
- Metriche merge PR
- (Merge medio 6g 17h) (9 PR mergiate in 30 g)
Descrizione
🔎 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]: ... })