Description
Bug Report
π Search Terms
intersection, mapped type, contextual type
π Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ
β― Playground Link
π» Code
type Action<TEvent extends { type: string }> = (ev: TEvent) => void;
interface MachineConfig<TEvent extends { type: string }> {
schema: {
events: TEvent;
};
on?: {
[K in TEvent["type"]]?: Action<TEvent extends { type: K } ? TEvent : never>;
} & {
"*"?: Action<TEvent>;
};
}
declare function createMachine<TEvent extends { type: string }>(
config: MachineConfig<TEvent>
): void;
createMachine({
schema: {
events: {} as { type: "FOO" } | { type: "BAR" },
},
on: {
FOO: (ev) => {
ev.type; // should be 'FOO', but `ev` is typed implicitly as `any`
},
},
});
π Actual behavior
An implicit any pop-ups when the contextual type could be, somewhat easily, provided.
π Expected behavior
This should just work π I know a workaround for this issue - the workaround is to use a single mapped type instead of an intersection and just "dispatch" to the correct value in the template~ part of the mapped type, like here. However, this is way less ergonomic than an intersection AND the mapped type is no longer homomorphic which could matter for some cases (well, the original mapped type here is not homomorphic either, but it could be)
I already have a draft PR open to fix this issue, here. I only need some help with the stuff mentioned in the comment here