Microsoft/TypeScript

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

Ouverte

#51 693 ouverte le 30 nov. 2022

 (5 commentaires) (7 réactions) (0 personne assignée)TypeScript (13 395 forks)batch import
Experience EnhancementHelp WantedSuggestion

Métriques du dépôt

Stars
 (108 860 étoiles)
Métriques de merge PR
 (Métriques PR en attente)

Description

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.

Guide contributeur