-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Open
Labels
BugA bug in TypeScriptA bug in TypeScriptDomain: check: Control FlowThe issue relates to control flow analysisThe issue relates to control flow analysis
Milestone
Description
TypeScript Version: 4.0.5, 4.1.0-beta, 4.2.0-dev.20201112
Search Terms:
- Multiple assertion methods
- "asserts this is"
- assertion "cfa"
Code
class X<T, Locked extends boolean> {
public x: null | T | (Locked extends true ? 1 : 2) = null
public assert<U>(): asserts this is X<U, Locked> { }
public lock(): asserts this is X<T, true> {}
}
const x: X<string | number, false> = new X<string | number, false>()
x.assert<string>()
// x is X<string, false> here
x.lock()Expected behavior:
Either:
- After
x.lock(),xis narrowed toX<string, true> - Or, the
x.lock()line throws at compile-time due to not being CFA'd
Actual behavior:
After x.lock(), x is narrowed to X<string, false> & X<string | number, true>.
Analysis:
x being typed as X<string, false> & X<string | number, true> shows that the x.lock() narrows from the original type (X<string | number, false>) instead of the narrowed type at that position (X<string, false>).
If instead a "top-level" assertion function is used the type is properly narrowed:
class X<T, Locked extends boolean> {
public x: null | T | (Locked extends true ? 1 : 2) = null
public assert<U>(): asserts this is X<U, Locked> { }
public lock(): asserts this is X<T, true> {}
}
const x: X<string | number, false> = new X<string | number, false>()
x.assert<string>()
// x is X<string, false> here
declare function lock<T>(v: X<T, boolean>): asserts v is X<T, true>
lock(x)This leads me to believe this is an issue with the x.lock() call not being CFA'd, in which case the correct behavior would be to throw ts(2775) on the x.lock() line.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
BugA bug in TypeScriptA bug in TypeScriptDomain: check: Control FlowThe issue relates to control flow analysisThe issue relates to control flow analysis