I'm having issues working with discriminated union and generic types.
I have a discriminated union type as follows:
interface A {
type: 'A',
payload: string,
}
interface B {
type: 'B',
payload: number,
}
type ALL = A | B;
I'd like to write a function that has a return type of the given payload
. The problem is that this function doesn't infer the type of payload
:
function doStuff <T extends ALL>(input: T): T['payload'] {
switch (input.type) {
case 'A':
// TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. Type 'string' is not assignable to type 'number'.
return processStringPayload(input.payload);
case 'B':
// TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. Type 'string' is not assignable to type 'number'.
return processNumberPayload(input.payload);
}
}
function processStringPayload(payload: string): string {
return payload;
}
function processNumberPayload(payload: number): number {
return payload;
}
Additionally, the return type is not respected:
function doStuff <T extends ALL>(input: T): T['payload'] {
switch (input.type) {
case 'A':
// 'A' should only support returning string
return 123;
case 'B':
// 'B' should only support returning number
return 'some string'
}
}
Edit: I am having this problem using TS 4.0. As mentioned in the comments, TS 4.3+ has improvements to discriminated unions.