Open
Description
Bug Report
When having objects with methods that return a boolean, the types don't get narrowed when checked, contrary to properties.
🔎 Search Terms
type guard, narrowing
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about type narrowing with methods returning strict literals in the types
⏯ Playground Link
Playground link with relevant code
💻 Code
class Some<T> {
public readonly value: T;
public constructor(value: T) {
this.value = value;
}
public isSome(): true { return true; }
}
class None {
public isSome(): false { return false; }
}
type Option<T> = Some<T> | None;
declare const x: Option<string>;
if (x.isSome()) {
x.value;
// Property 'value' does not exist on type 'Option<string>'.
// Property 'value' does not exist on type 'None'.(2339)
}
🙁 Actual behavior
isSome()
does not narrow the type from Option<string>
to Some<string>
unless the return type of isSome()
in either or both classes are typed as this is Some<T>
:
Some#isSome() |
None#isSome() |
Narrows? |
---|---|---|
true |
false |
❌ |
this is Some<T> |
false |
✅ |
true |
this is Some<any> |
✅ |
this is Some<T> |
this is Some<any> |
✅ |
This behaviour is not consistent to the one when typed properties (public some: true = true
/public some: false = false
) are used, where the type narrowing system works perfectly fine.
🙂 Expected behavior
isSome()
would be sufficient to narrow Option<string>
to Some<string>
, as is the case with regular properties (Playground link). In short, the first case in the aforementioned table should work.