I'm facing a specific scenario:
There's a function that takes in a boolean and returns either a RealItem
or an ImaginaryItem
. I'm using conditional types to determine the return type based on the boolean argument.
type RealItem = { color: string }
type ImaginaryItem = { description: string }
export function createItem<T extends boolean>(isReal: T): T extends true ? RealItem : ImaginaryItem
export function createItem<T extends boolean>(isReal: T): RealItem | ImaginaryItem {
return isReal ? { color: 'red' } : { description: 'Crazy thing' }
}
The function signatures work as expected for the following scenarios:
const a = createItem(true) | typeof a -> RealItem
const b = createItem(false) | typeof b -> ImaginaryItem
let isReal = true
const a = createItem(isReal) | typeof a -> RealItem
let isReal = false
const b = createItem(isReal) | typeof b -> ImaginaryItem
However, when I wrap the createItem
function in another function and pass the isReal
argument:
const itemsFactory = (isReal: boolean) => createItem(isReal)
TypeScript fails to infer the narrowed return type with conditional return type:
const a = itemsFactory(true) | typeof a -> RealItem | ImaginaryItem
const b = itemsFactory(false) | typeof b -> RealItem | ImaginaryItem
The union type is causing some dissatisfaction for me.
- Is this a limitation of TypeScript in terms of type inference?
- How can I guide TypeScript to better interpret higher function arguments?
I understand that type guards could be used here, but they are not compatible with my current code structure.