3

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.

sthomps
  • 4,480
  • 7
  • 35
  • 54
  • Does this answer your question? [Discriminated Union of Generic type](https://stackoverflow.com/questions/50870423/discriminated-union-of-generic-type) – Jeff Bowman Dec 17 '21 at 00:42
  • [I cannot reproduce your first issue](https://tsplay.dev/NnX9eW); could you please make sure that you are providing a [mre] that can be dropped into a standalone IDE to demonstrate what you're seeing? You might need to pay attention to your compiler options and version of TypeScript. If it turns out that your issue is only reproducible on an older version of TypeScript then the answer might be "update to the latest stable version". – jcalz Dec 17 '21 at 03:00
  • By the way, eventually (TS 4.6+) you will be able to safely discriminate the union with generics, like [this](https://tsplay.dev/Wk59DN), using the fixes in [ms/TS#47109](https://github.com/microsoft/TypeScript/pull/47109) to address the use cases in [ms/TS#30581](https://github.com/microsoft/TypeScript/issues/30581). But as you see it requires a significant refactoring. Let me know if you want an answer that describes what's going on here, after you verify whether or not your first issue is really present. – jcalz Dec 17 '21 at 03:10
  • @jcalz ah you are correct about the version. I am able to reproduce my problem using your [playground example on TS 4.0.5](https://www.typescriptlang.org/play?ts=4.0.5#code/JYOwLgpgTgZghgYwgAgILIN4ChnLATwAcIAuZAclXIBodlC58AbAezgBMyBnMKUAc1oBfLFlCRYiFACFMdAsTLlpNOg2ZtOyEAFcAtgCNow0QpSoAMheQBeNMgA+yaQG5RWGDpAIwwFiGR2FgBlMB0YGAAeABVkCAAPSBB2LjQrAD4AClBCHTAyaIBKAoBtcnVWDnIAXTlcLgB3YDAEAAtkbJBcsAA6M0K63GQEOC4USnISOiHkKAgwqADCKBYkLi5QvhB+AAVGSvZO7p6KzUK3GZGxihUpmdw5haWVta4AOX0jKD2NDiO8k77M4XZAiEQeLw+PzPVYQdabAQ-A6ZU4cbi8ATFZA8Lb8QaPHSLehAjhucGeby+fz0F5w96faBIzQoklaXSGaBY9lffHzQlLVlk9xAA) – sthomps Dec 17 '21 at 16:38
  • Okay, so what should be done for this question? Do you want to [edit] it so that it asks only about problems that remain in the current stable version (TS 4.5)? Or do you want to make it clear that you need an answer that works for TS4.0? – jcalz Dec 17 '21 at 16:45
  • @jcalz I found an alternate [solution](https://www.typescriptlang.org/play?ts=4.0.5#code/JYOwLgpgTgZghgYwgAgILIN4ChnLATwAcIAuZAclXIBodlC58AbAezgBMyBnMKUAc1oBfLFlCRYiFACFMdAsTLlpNOg2ZtOyEAFcAtgCNow0QpSoAMheQBeNMgA+yaQG5RMHSARhgLEMnYWAGUwHRgYAApQQh0wMlQASm5eATcPLx8-AODQ8KiQGLjnJO19Iyg0z29ff0CQsMjo2PirEssLAG1ydVYOcgBdOVwuAHdgMAQAC2R8woA6MwSh3GQEOC4USnISOhXkKAhQqH9CKBYkLi4QvhB+AAVGXvZZ2LmezQS3PbWNihUdva4A5HE5nC5cAByZWgDw0HBeYDejw+X2QIhEWHS1Syp3OEEu1wEsKeEXeHGSN34JR4lOWwJ0x3oyI4bgxWMyoLxlyhhhhzOeZK0ul5UBKwvKdMODJO-NZoiwQA) that works for TS 4.0 using function overloads. I can revise the question. – sthomps Dec 17 '21 at 17:55

0 Answers0