-
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
Discriminating property with never as possible type makes its enclosing object type disappear when narrowing #60702
Comments
Related: #38144 I don't really see how a |
@MartinJohns the point is not using |
(not a TS team member) This is behaving as intended. You can never witness a value of type |
One example of using The problem I opened an issue for doesn't occur with the above for some reason. When a condition is checked on If you add a literal type to the mix like I did the enclosing type of |
Can you show an example where Let's say you have an I guess I'll wait for the TS team to chime in. |
@jcalz In the referenced code they assert the absence of I mean, we can talk about this usage of The point is that when the property is considered discriminant (because of the presence of a literal type?) the enclosing type of |
It seems like you're using It's correct behavior for an object type with a property of type |
While checking the new failures generated by #60718 in mainstream repositories I found the following behaviour when // adapted from continue codebase
type PackageDocsResult = (
| { details?: never; error: "disc"; }
| { details: string; error?: never }
);
declare const pdr: PackageDocsResult;
if (typeof pdr.error === "string") {
pdr
// ^? { details?: never; error: "disc"; } (OK)
} else {
pdr
// ^? never (???)
} In this situation the This is what TS already does, you can check it here. The problem arises with Edit: type PackageDocsResult = (
| { details: never; error: "disc"; }
| { details: string; error: never }
); As we discussed, it's okay if the enclosing object of a discriminating property typed as |
Marking in discussion since I think the PR seems much better overall than we'd have expected in terms of perf impact |
@RyanCavanaugh I must admit that both your explanation and @jcalz's one have convinced me, and I now find this behaviour of TypeScript more reasonable. I had opened this issue because, upon encountering the problem with It seems that the change to the name prop type from It could then be suggested to type PackageDocsResult = {
packageInfo: ParsedPackageInfo;
} & (
| { error: string; details?: never }
| { details: PackageDetailsSuccess; error?: never }
); to: type PackageDocsResult = {
packageInfo: ParsedPackageInfo;
} & (
| { error: string; }
| { details: PackageDetailsSuccess; }
);
// or the following, that seems to work under their configuration
type PackageDocsResult = {
packageInfo: ParsedPackageInfo;
} & (
| { error: string; details?: undefined }
| { details: PackageDetailsSuccess; error?: undefined }
); Unfortunately, I don’t think they intend to enable
In any case, seeing a constituent of a union disappear into nothing-ness can be an unexpected behavior, even if correct, and my PR certainly increases the cases in which this happens. It might be worth considering a linter rule to handle these situations. The rule should discourage declaring properties with a |
🔎 Search Terms
discriminated union never, discriminating property never
🕗 Version & Regression Information
It happens in every version I tried.
⏯ Playground Link
https://www.typescriptlang.org/play/?ts=5.8.0-dev.20241206#code/C4TwDgpgBAIglgZwMYFUB2cD2aoF4BQAPlAN5QAmiSACgE6ZgBcUaEAbhLQDRQCGzARigBfIqQpU6DZgCIw9MDJ4AjZgCYRYspWRSmUAK5pyEAGZxW5HkmYBmTfhNIANr1rQk2BMCiZm8ZHQsNHx8OFMACkwAOh0aBQBKUnwoXxSoAHoMqAA9AH58YSgIZwRoEnTMdKzcgtEwyIBCGLi9JIrUqtSa-MLi0vLK6uze4SA
💻 Code
🙁 Actual behavior
{ discProp: never, a: 1 }
disappears!🙂 Expected behavior
In the first
if
, I expect{ discProp: never, a: 1 }
to be a possible type ofo
in theelse
branch. Viceversa, in the secondif
I expect it to be a possible type ofo
in thethen
branch.Additional information about the issue
No response
The text was updated successfully, but these errors were encountered: