Skip to content

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

@slinkydeveloper

Description

@slinkydeveloper

πŸ”Ž 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Help WantedYou can do thisPossible ImprovementThe current behavior isn't wrong, but it's possible to see that it might be better in some cases

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions