Skip to content

Discriminated union pattern fails to narrow type with ReturnType and inferenced function type #26730

Closed
@mserranom

Description

@mserranom

TypeScript Version: 3.0.1 and 3.1.0-dev.20180829

Search Terms:

Code

type A = {
  type: "A";
  aprop: number;
};

type B = {
  type: "B";
  bprop: number;
};


function aFunc() {
    return { type: "A", aprop: 2 }
};

function bFunc() {
    return { type: "B", bprop: 2 }
};


function aFuncTyped(): A {
    return { type: "A", aprop: 2 }
};

function bFuncTyped(): B {
    return { type: "B", bprop: 2 }
};


// 1. Discriminated with ReturnType of explicitely typed functions: all good.

let x2: ReturnType<typeof aFuncTyped> | ReturnType<typeof bFuncTyped>;

if (x2.type === "A") {
  x2.aprop;
}

if (x2.type === "B") {
  x2.bprop;
}

// 2. Discriminated with ReturnType of implicitely typed functions: errors.

let x3: ReturnType<typeof aFunc> | ReturnType<typeof bFunc>;

if (x3.type === "A") {
  // Property 'aprop' does not exist on type '{ type: string; aprop: number; } | { type: string; bprop: number; }'.
  // Property 'aprop' does not exist on type '{ type: string; bprop: number; }'.
  x3.aprop;
}

if (x3.type === "B") {
  // Property 'bprop' does not exist on type '{ type: string; aprop: number; } | { type: string; bprop: number; }'.
  // Property 'bprop' does not exist on type '{ type: string; aprop: number; }'.
  x3.bprop;
}

Expected behavior:

Should not fail to compile.

ReturnType infers correctly the type of afunc() and bfunc(), however it fails to apply the correct discriminate in the if statements.

Actual behavior:

Fails to compile with the error messages indicated in code.

Playground Link:
https://www.typescriptlang.org/play/#src=type%20A%20%3D%20%7B%0D%0A%20%20type%3A%20%22A%22%3B%0D%0A%20%20aprop%3A%20number%3B%0D%0A%7D%3B%0D%0A%0D%0Atype%20B%20%3D%20%7B%0D%0A%20%20type%3A%20%22B%22%3B%0D%0A%20%20bprop%3A%20number%3B%0D%0A%7D%3B%0D%0A%0D%0A%0D%0Afunction%20aFunc()%20%7B%0D%0A%20%20%20%20return%20%7B%20type%3A%20%22A%22%2C%20aprop%3A%202%20%7D%0D%0A%7D%3B%0D%0A%0D%0A%0D%0Afunction%20bFunc()%20%7B%0D%0A%20%20%20%20return%20%7B%20type%3A%20%22B%22%2C%20bprop%3A%202%20%7D%0D%0A%7D%3B%0D%0A%0D%0A%0D%0Afunction%20aFuncTyped()%3A%20A%20%7B%0D%0A%20%20%20%20return%20%7B%20type%3A%20%22A%22%2C%20aprop%3A%202%20%7D%0D%0A%7D%3B%0D%0A%0D%0Afunction%20bFuncTyped()%3A%20B%20%7B%0D%0A%20%20%20%20return%20%7B%20type%3A%20%22B%22%2C%20bprop%3A%202%20%7D%0D%0A%7D%3B%0D%0A%0D%0A%0D%0A%0D%0A%2F%2F%201.%20Discriminated%20with%20ReturnType%20of%20explicitely%20typed%20functions%3A%20all%20good.%0D%0A%0D%0Alet%20x2%3A%20ReturnType%3Ctypeof%20aFuncTyped%3E%20%7C%20ReturnType%3Ctypeof%20bFuncTyped%3E%3B%0D%0A%0D%0Aif%20(x2.type%20%3D%3D%3D%20%22A%22)%20%7B%0D%0A%20%20x2.aprop%3B%0D%0A%7D%0D%0A%0D%0Aif%20(x2.type%20%3D%3D%3D%20%22B%22)%20%7B%0D%0A%20%20x2.bprop%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F%202.%20Discriminated%20with%20ReturnType%20of%20implicitely%20typed%20functions%3A%20errors.%0D%0A%0D%0Alet%20x3%3A%20ReturnType%3Ctypeof%20aFunc%3E%20%7C%20ReturnType%3Ctypeof%20bFunc%3E%3B%0D%0A%0D%0Aif%20(x3.type%20%3D%3D%3D%20%22A%22)%20%7B%0D%0A%20%20%2F%2F%20Property%20'aprop'%20does%20not%20exist%20on%20type%20'%7B%20type%3A%20string%3B%20aprop%3A%20number%3B%20%7D%20%7C%20%7B%20type%3A%20string%3B%20bprop%3A%20number%3B%20%7D'.%0D%0A%20%20%2F%2F%20Property%20'aprop'%20does%20not%20exist%20on%20type%20'%7B%20type%3A%20string%3B%20bprop%3A%20number%3B%20%7D'.%0D%0A%20%20x3.aprop%3B%0D%0A%7D%0D%0A%0D%0Aif%20(x3.type%20%3D%3D%3D%20%22B%22)%20%7B%0D%0A%20%20%2F%2F%20Property%20'bprop'%20does%20not%20exist%20on%20type%20'%7B%20type%3A%20string%3B%20aprop%3A%20number%3B%20%7D%20%7C%20%7B%20type%3A%20string%3B%20bprop%3A%20number%3B%20%7D'.%0D%0A%20%20%2F%2F%20Property%20'bprop'%20does%20not%20exist%20on%20type%20'%7B%20type%3A%20string%3B%20aprop%3A%20number%3B%20%7D'.%0D%0A%20%20x3.bprop%3B%0D%0A%7D%0D%0A%0D%0A%0D%0A

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions