Description
Bug Report
When assigning the value 0 or 1 to the field of an object, see below, type widening infers the type number
. When doing the same through a generic higher-order function, the field gets the type 0 | 1
. This can trigger a type error when using that value in another generic high-order function that assigns to the object as a side-effect.
🔎 Search Terms
type widening
inconsistency
🕗 Version & Regression Information
Appears in all versions on Playground (back to 3.3.3333).
Also appears in Nightly (v. 5.0.0.-dev20221116)
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about widening
⏯ Playground Link
Playground link with relevant code
💻 Code
// The following example works by type widening
function wrap<L>(v: L): { val: L } {
return { val: v };
}
export function thisworks(): number {
const g = (b: boolean) => { return b ? 1 : 0; }
let o = wrap(g(true));
o /// Type: o: { val: number }
o.val += 1;
// o.val : number
return o.val;
}
// The following example does exactly the same but combines `wrap` and `g`
// into a single call to a high-order function.
// Now type-widening doesn't apply.
function applyWrap<L>(b: boolean, map: (b: boolean) => L): { val: L } {
return { val: map(b) };
}
function mapVal<L>(o: { val: L }, map: (arg: L) => L): void {
o.val = map(o.val);
}
export function doesntwork(): { val: number } {
let o = applyWrap(true, (b: boolean) => { return b ? 1 : 0; });
o /// Type: o: { val: 0 | 1 }
// The next line triggers an error by again preventing type widening in the assignment
mapVal(o, v => { return v + 1; });
// This line would have worked:
// o.val += 1
return o;
}
🙁 Actual behavior
I get a type error in the function doesntwork
on the mapVal
call. This is because type widening did not apply as expected to o
, so it has type { val: 0 | 1 }
. Simultaneously, type widening is also disabled at the mutation mapVal
-- simply writing o.val += 1
instead of the mapVal
call would have worked.
🙂 Expected behavior
I expected that the behaviour of type widening remains the same in the case of using high-order callbacks to generate the value and not.