Bug: null can be excluded by !== null in flow before typeof === 'object', but not excluded by predicate function.
#60.102 geöffnet am 30. Sept. 2024
Repository-Metriken
- Stars
- (48.455 Stars)
- PR-Merge-Metriken
- (Durchschn. Merge 6T 17h) (9 gemergte PRs in 30 T)
Beschreibung
🔎 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.