-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
Bug Report
🔎 Search Terms
discriminated union, discriminant, interpolated template literal, contextual typing, delayed, deferred
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about discriminated unions
⏯ Playground Link
Playground link with relevant code
💻 Code
type S = { d: "s"; cb: (x: string) => void; };
type N = { d: "n"; cb: (x: number) => void; };
declare function foo(foo: S | N): void;
foo({ d: "n", cb: x => x.toFixed() }); // okay
foo({ d: "s", cb: x => x.toUpperCase() }); // okay
foo({ d: `${"s"}`, cb: x => x.toXXX() }); // error!
// ------------------> ~
// Parameter 'x' implicitly has an 'any' type.
🙁 Actual behavior
In the third call to foo()
, the discriminant property d
is an interpolated template literal whose type is correctly seen to be "s"
, but the cb
property's callback parameter x
is not contextually typed as string
and instead implicitly falls back to any
.
🙂 Expected behavior
The third call to foo()
should behave just like the second call to foo()
, where the object is narrowed to S
and therefore cb
's parameter is contextually typed as string
.
Notes
Comes from this Stack Overflow question
I'm imagining this is just a design limitation where the type of d
is computed too late for it to be available when the contextual typing for cb
happens. A similar failure occurs when the discriminant is the output of an inline function call:
function justS(): "s" { return "s" };
foo({ d: justS(), cb: x => x.toXXX() }); // error!
// -----------------> ~
// Parameter 'x' implicitly has an 'any' type.
I searched around for an existing issue but I didn't find an exact enough match. There's #35769 / #41759 / #46847, for example... related but not obviously the same.
The obvious workaround is just to do the interpolation ahead of time into a const
and use that instead:
const s = `${"s"}` as const;
foo({ d: s, cb: x => x.toUpperCase() }); // okay
Mostly I'm just looking for an official status on this (and expecting it to be Design Limitation).