-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Contextual typing fails when discriminant is an interpolated template literal #53888
Comments
This feels like one of those “you were trying to break it and succeeded” type deals that will likely not be considered worth fixing since it’s unlikely anyone would hit it by accident and/or be blocked by it (i.e. “Why would you write it this way?” ~ Future Ryan, probably) |
This SO question was asked by someone who is apparently blocked by it; presumably their actual code is less contrived. I agree that it's probably not going to be considered worth addressing, though. |
Hmm, while it doesn't invalidate the OP here, that SO question has this type: type BiomePlainLinkProps = {
href: string;
onClick?: (event: string) => void;
}
type BiomeButtonProps = {
href?: never;
onClick?: (event: number) => void;
}
type ClickableDiscriminatedUnion =
| BiomePlainLinkProps
| BiomeButtonProps; I'm not even sure that's a valid discriminated union? I thought the discriminant had to be a literal type (or at least a union of them), not just |
The discriminant there is an optional |
This seems wrong; the example as presented isn't any more difficult to resolve than this one: type S = { d: "s" | "t"; cb: (x: string) => void; };
type N = { d: "n"; cb: (x: number) => void; };
declare const dv: "s" | "t";
foo({ d: dv, cb: x => x.toXXX() }); // does the right thing |
Bug Report
🔎 Search Terms
discriminated union, discriminant, interpolated template literal, contextual typing, delayed, deferred
🕗 Version & Regression Information
⏯ Playground Link
Playground link with relevant code
💻 Code
🙁 Actual behavior
In the third call to
foo()
, the discriminant propertyd
is an interpolated template literal whose type is correctly seen to be"s"
, but thecb
property's callback parameterx
is not contextually typed asstring
and instead implicitly falls back toany
.🙂 Expected behavior
The third call to
foo()
should behave just like the second call tofoo()
, where the object is narrowed toS
and thereforecb
's parameter is contextually typed asstring
.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 forcb
happens. A similar failure occurs when the discriminant is the output of an inline function call:Playground link
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:Playground link
Mostly I'm just looking for an official status on this (and expecting it to be Design Limitation).
The text was updated successfully, but these errors were encountered: