It appears that you are attempting to create something similar to this:
type StringOrNumber<T extends boolean> = T extends true ? string : number
However, this will not be utilized in flow analysis. Therefore, the type will not be correctly inferred within an if
block.
function makeUsername<T extends boolean>({ data, userExists }: { data: StringOrNumber<T>; userExists: T }): any {
if (userExists) {
// The data remains as StringOrNumber<T> here. Manual casting is required.
const dataStr = data as string;
} else {
const dataNum = data as number;
}
}
// Although it works correctly during the function call
makeUsername({data: '12', userExists: true}) // ok
makeUsername({data: 12, userExists: true}) // error
It may be more appropriate to use function overloads in this scenario:
function makeUsername({ data, userExists }: { data: string; userExists: true }): any;
function makeUsername({ data, userExists }: { data: number; userExists: false }): any;
function makeUsername({ data, userExists }: { data: string | number; userExists: boolean }): any {
if (userExists) {
// Type casting is still necessary here...
const dataStr = data as string;
} else {
const dataNum = data as number;
}
}
// On the bright side, the function calls work as expected with the overloads.
makeUsername({ data: 'kyo', userExists: true }) // ok
makeUsername({ data: 'kyo', userExists: false }); // error