Skip to content

Control flow analysis for dependant parameters does not work with complex typesΒ #51693

Open
@andyearnshaw

Description

@andyearnshaw

Bug Report

πŸ”Ž Search Terms

dependant parameters
discriminated union parameters

πŸ•— Version & Regression Information

TypeScript 4.6.x -> TypeScript 4.9.3 & Nightly

  • This is the behavior in every version I tried, and I reviewed the FAQ

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

The release notes for 4.6 explain how control flow analysis for dependant parameters can work for functions whose arguments are defined as tuples:

type Func = (...args: ["a", number] | ["b", string]) => void;

const f1: Func = (kind, payload) => {
    if (kind === "a") {
        payload.toFixed();  // 'payload' narrowed to 'number'
    }
    if (kind === "b") {
        payload.toUpperCase();  // 'payload' narrowed to 'string'
    }
};

f1("a", 42);
f1("b", "hello");

However, as soon as you use a more complex type, the code no longer compiles:

type A = { kind: "a"; }
type B = { kind: "b"; }

type Func = (...args: [A, number] | [B, string]) => void;

const f1: Func = ({ kind }, payload) => {
    if (kind === "a") {
        payload.toFixed();  // 'payload' should be narrowed to 'number'
    }
    if (kind === "b") {
        payload.toUpperCase();  // 'payload' should be narrowed to 'string'
    }
};

f1({ kind: "a" }, 42);
f1({ kind: "b" }, "hello");

πŸ™ Actual behavior

On the line with payload.toFixed(), TypeScript gives the following compiler error:

Property 'toFixed' does not exist on type 'string | number'.
  Property 'toFixed' does not exist on type 'string'.

On the line with payload.toUpperCase(), TypeScript gives the following compiler error:

Property 'toUpperCase' does not exist on type 'string | number'.
  Property 'toUpperCase' does not exist on type 'number'.(2339)

πŸ™‚ Expected behavior

I would expect TypeScript to apply the same control flow analysis for the more complex typed parameters as the simple ones. I'm actually trying to use this feature while playing around with the new decorators that @rbuckton has been working on. I want to make a property decorator work with both accessors and setters, taking advantage of control flow analysis to return the appropriate value without casting.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions