microsoft / microsoft/TypeScript
Bug: null can be excluded by !== null in flow before typeof === 'object', but not excluded by predicate function.
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 117
Description
🔎 Search Terms
"null", "control flow", "narrowing", "narrow", "exclusion", "object", "typeof"
🕗 Version & Regression Information
Potentially, we could expect the behaviors of if (a === null) and if ((v => v !== null)(a)) (inferred as predicate since TS 5.5) should be the same, but it's actually not in specific cases.
If it's combined with typeof a === 'object' check in the same flow, first one is correctly omits the null possibility, while second one doesn't.
- This changed between versions:
- I confirmed that the exclusion in flow can be done since TS4.5. It's not regression, but the new feature seems to have been partially applied.
- TS4.4 https://www.typescriptlang.org/play/?ts=4.4.4#code/MYewdgzgLgBAlhAcgVwDapgXhgCgG4BcMyYA1mCAO5gCURe8EMYaGmAfDA5j86wNwAoAPTCY4mAD0A-INCRYAMyy4AhkRLkqtLJwDegifGU4EKdDlU0aMAE4BTKMltghRuCagBPAA72QyqowAIS8AOQgAEYAVvbAUGE2Dk4ubhKqbqJSsgC+QoJy4NAwAOYqlhpkFNQ2HDAG7iZBPNgs6EmOzq6GEh643n4BMEGh2BExcQkdKd1GGYZZMoJ5QA
- TS4.5 https://www.typescriptlang.org/play/?ts=4.5.5#code/MYewdgzgLgBAlhAcgVwDapgXhgCgG4BcMyYA1mCAO5gCURe8EMYaGmAfDA5j86wNwAoAPTCY4mAD0A-INCRYAMyy4AhkRLkqtLJwDegifGU4EKdDlU0aMAE4BTKMltghRuCagBPAA72QyqowAIS8AOQgAEYAVvbAUGE2Dk4ubhKqbqJSsgC+QoJy4NAwAOYqlhpkFNQ2HDAG7iZBPNgs6EmOzq6GEh643n4BMEGh2BExcQkdKd1GGYZZMoJ5QA
- This changed in commit or PR (not sure for now, sorry)
⏯ Playground Link
💻 Code
const isNull = (v: unknown) => v === null;
// ^?
const f = (a: unknown) => {
if (isNull(a)) return;
if (typeof a !== 'object') return;
a;
// ^?
};
const g = (a: unknown) => {
if (a === null) return;
if (typeof a !== 'object') return;
a;
// ^?
};
🙁 Actual behavior
Last a in f is inferred as object | null.
🙂 Expected behavior
Last a in f would be inferred as object.
Additional information about the issue
Here is important to check typeof === 'object' after the check for null, because type narrowing step is formally, unknown → object | null → object. === null alone cannot narrow anything on unknown.
If you swap the if-statements in above, you can see both is inferred as object.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the TypeScript Playground links and the minimal reproductions for f and g, comparing the inferred types after the typeof check. Trace the control-flow narrowing and inferred predicate behavior responsible for the difference; done means the predicate case narrows a to object without null, with regression coverage for the reported example.
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