microsoft / microsoft/TypeScript

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

Open
#62,306 6 comments 0 reactions 0 assignees View on GitHub
Domain: check: Contextual Types Help Wanted Possible Improvement
Dominant language
Go
Stars
111k
Forks
14.3k
PR merge metrics
PR metrics pending

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

```ts
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

Open the contributing guide

Research direction

Reproduce the examples in the linked TypeScript Playground, comparing test4 with test7 and the explicitly discriminated cases. Trace how contextual typing handles the union containing a function variant, then add a regression test covering the missing discriminant case and verify that the callback parameter is inferred correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.