Microsoft/TypeScript

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

Open

#51,693 建立於 2022年11月30日

在 GitHub 查看
 (5 留言) (7 反應) (0 負責人)TypeScript (6,726 fork)batch import
Experience EnhancementHelp WantedSuggestion

倉庫指標

Star
 (48,455 star)
PR 合併指標
 (平均合併 6天 17小時) (30 天內合併 9 個 PR)

描述

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.

貢獻者指南