Microsoft/TypeScript

Contextual typing doesn't work when mixing up discriminated unions with function variant

Open

#62,306 opened on Aug 20, 2025

View on GitHub
 (6 comments) (0 reactions) (0 assignees)TypeScript (48,455 stars) (6,726 forks)batch import
Domain: check: Contextual TypesHelp WantedPossible Improvement

Description

🔎 Search Terms

contextual typing, discriminated unions

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries
  • Tested with TS 5.4.5 and TS 5.9.2

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/C4TwDgpgBAcg9sA6nATgawJYDsDmBVLDOLKAXgCgoqoAfKACnoDcBDAGwFcIAuKLDgLYAjCCgCUZAHxQmcDABMxlanQDey6tQwBnAMrAU2HLwNcA3Bs1QAZll6NWnHlG0GjE0tNkKxFzQF9LNUsdfUNcAH5ea3ZtCD9qW3tmdi5efmFRDy85RQt-C3IAY2JXKGAIVwBGXngkVExcAiISUgYWbKhVAuLS4HLK4AAmWoRkdCNm4jIukL03XBMULgAaSyT2zu7yHpKsMorXAGZR+ommwmm29U1QheMbWIg1zQ36DqkuwN2+gdcAFlO40a+EurVmrzsm0+2x65FAkCgwMmYLIQQhViod3CD1M8UskOSjjSLnunW8eUsgU0wVu8xxUUebDiCSobxSTnSghE4k+FN8O0KewOgwArLxkRcWjMblp6UYlqt1lD3ltvhZhf1DsAAGwShoo6XXOZhBVMuIvRIqj6eL6C3r7LWDADs+vOoKNGLZ1rVgqAA

💻 Code

type NotWorkingUnion =
    | ((value: number) => void)
    | {
        isString: true;
        fn: ((value: string) => void);
    }
    | {
    isString?: false;
    fn: ((value: number) => void);
};

const test1: NotWorkingUnion = (a) => {}; // Works
const test2: NotWorkingUnion = { // Works
    isString: true,
    fn: (a) => {}
};
const test3: NotWorkingUnion = { // Works
    isString: false,
    fn: (a) => {}
};
const test4: NotWorkingUnion = { // Doesn't work!
    fn: (a) => {}
};

type WorkingUnion =
    | {
        isString: true;
        fn: ((value: string) => void);
    }
    | {
    isString?: false;
    fn: ((value: number) => void);
};

const test5: WorkingUnion = { // Works
    isString: true,
    fn: (a) => {}
};
const test6: WorkingUnion = { // Works
    isString: false,
    fn: (a) => {}
};
const test7: WorkingUnion = { // Works
    fn: (a) => {}
};

🙁 Actual behavior

Contextual typing breaks when an union is both discriminated by a field and one of the union variants is just a function

🙂 Expected behavior

Contextual typing should correctly work, as the type system should have enough information to discriminate between a function and an object with or without the field

Additional information about the issue

strict mode is enabled.

Contributor guide