Reputation: 158
Let's say we have some kind of dispatch functions that tries to update a certain prop on an object. Is it possible to have proper type inference in the following scenario?
type EntityA = {
name: string;
id: number
}
type EntityB = {
id: number;
test1: number;
test2: string;
test3: number;
test4: string;
}
type EntityAction<T> = {
[K in keyof T]-?:
| {
type: 'UPDATE_ENTITY';
payload: T;
} |
{
type: 'UPDATE_PROP';
propName: K;
payload: T[K];
};
}[keyof T];
function dispatch<T>(action: EntityAction<T>) {
// omitted logic because it's not relevant
console.log(action);
}
dispatch<EntityA>({
type: 'UPDATE_PROP',
propName: 'name',
});
dispatch<EntityB>({
type: 'UPDATE_PROP',
propName: 'test4',
payload: ''
})
I managed to infer the types based on a reply found here (Thanks @jcalz) but as soon as I have more than 1 prop in a type it doesn't work correctly.
Given EntityA, if i dispatch the following:
dispatch<EntityA>({ type: 'UPDATE_PROP',propName: 'id' })
it correctly lets me know that the prop payload
is missing
However, if I pass
dispatch<EntityA>({ type: 'UPDATE_PROP',propName: 'name' })
It tells me that
Type '"name"' is not assignable to type '"id"'.
(or whatever the last prop in the type is).
Any idea if this can be "fixed" to properly infer the type of payload
? Is it even possible in this setup?
It seems to work if EntityAction as:
export type EntityAction<T> = {
[K in keyof T]-?:
{
type: 'UPDATE_PROP';
propName: K;
payload: T[K];
};
}[keyof T];
Upvotes: 0
Views: 76
Reputation: 330411
This looks like a known bug, reported at microsoft/TypeScript#46374, in which an "incomplete" value assigned to a discriminated union yields a compiler error which complains about the wrong property.
It looks like it was introduced in TypeScript 3.9, sometime between [email protected]
and [email protected]
, which leads me to believe that it was probably caused by the work done in microsoft/TypeScript#37589, "Disallow partial matches for discriminant properties when generating error messages", which changed the way discriminated union error messages were generated, fixing a different bug but apparently causing this one.
Anyway, the bug is currently scheduled to be fixed for TypeScript 5.1, but it has been rescheduled several times already, so it's not clear if this will actually happen.
Upvotes: 1