Search code examples
typescriptunion-typesgeneric-type-argument

Typescript function whose return type depends on a generic


I'm trying to write a function whose return type depends on a generic argument. Here's a snippet of code to demonstrate:

type FOOBAR = 'foo' | 'bar';

function fn<T extends FOOBAR>(arg: T): T extends 'foo' ? 'r1' : 'r2' {
  if (arg === 'foo') {
    return 'r1';
  }
  return 'r2';

}

const fooResponse = fn('foo'); // this is correctly typed as 'r1'
const barResponse = fn('bar'); // this is correctly typed as 'r2'

Within the function body, I see Type '"r1"' is not assignable to type 'T extends "foo" ? "r1" : "r2"'.. It's not clear to me how to resolve this complaint.

I do see a number of related questions, but none which address the combination of dependent return types with union types. The closest I could find is this, which seems to imply that it is currently impossible, though I'm not exactly sure.


Solution

  • You could use function overloads:

    type FOOBAR = 'foo' | 'bar';
    
    function fn(arg: 'foo'): 'r1';
    function fn(arg: 'bar'): 'r2';
    function fn(arg: FOOBAR) {
      if (arg === 'foo') {
        return 'r1';
      }
      return 'r2';
    }
    
    const fooResponse = fn('foo'); // this is correctly typed as 'r1'
    const barResponse = fn('bar'); // this is correctly typed as 'r2'