TS: Conditional property based on the value of a generic

101 Views Asked by At

Here I have a stripped down code snippet to demonstrate the sort of thing I'm trying to achieve:

interface A<RequiresB extends boolean = true> {
  alwaysRequired: string
  b: RequiresB extends true ? string : string | undefined
}

function getA<RequiresB extends boolean>(requiresB: boolean): A<RequiresB> {
  if (requiresB) {
    return {
      alwaysRequired: 'hello',
      b: 'world'
    }
  }

  return {
    alwaysRequired: 'hello',
    b: undefined
  }
}

The second return statement is failing with the following error: Type 'undefined' is not assignable to type 'RequiresB extends true ? string : string | undefined'.

I thought TypeScript would be clever enough to know that because requiresB is false at this point, it should allow the value of b in the return statement to be undefined.

So far, the only workaround I can find is by casting the return type like:

return {
  alwaysRequired: 'hello',
  b: undefined
} as A<RequiresB>

However that's not ideal, because with that solution, I could be missing the alwaysRequired value altogether and TypeScript wouldn't care.

Aside from refactoring the code altogether to not use the generics in this way, is there anything obvious I'm missing? It feels like there should be a way to get it to work.

0

There are 0 best solutions below