Skip to content

Misleading error message "'{}' and 'number' have no overlap" #60583

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

Open
kirkwaiblinger opened this issue Nov 25, 2024 · 2 comments
Open

Misleading error message "'{}' and 'number' have no overlap" #60583

kirkwaiblinger opened this issue Nov 25, 2024 · 2 comments
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript

Comments

@kirkwaiblinger
Copy link

kirkwaiblinger commented Nov 25, 2024

πŸ”Ž Search Terms

empty object type, unintentional comparison

πŸ•— Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play/?noUncheckedIndexedAccess=true&target=99&ts=5.8.0-dev.20241124#code/JYMwBAFA3gvmC8iwAYCUZZA

πŸ’» Code

if ({} === 0) {}

πŸ™ Actual behavior

TS 2367: "This comparison appears to be unintentional because the types '{}' and 'number' have no overlap."

πŸ™‚ Expected behavior

TS 2367: "This comparison appears to be unintentional because the types 'object' and 'number' have no overlap."

Additional information about the issue

the type {} and number do have overlap; number is a subset of {}.

declare const n: number;
// allowed!
const emptyObjectType: {} = n;

TS is correct to report an error, but it should give a technically correct reason for the error.

Analogous (very contrived) examples can be made for similar coincidentally-including-primitive types, like

// This comparison appears to be unintentional because the types '{ toFixed(): string; toPrecision(): string; }' and 'number' have no overlap.
if ({ toFixed(): string { return "" }; toPrecision(): string { return "" }} === 0) {}

// yet this is allowed
const numbery: { toFixed(): string; toPrecision(): string; } = 0;

Stems from discord discussion beginning here: https://discord.com/channels/508357248330760243/508357638677856287/1310419206260654081

Closely related to discussion regarding #60582

@RyanCavanaugh
Copy link
Member

Error messages are supposed to clue you into what's wrong, not be a language spec, and "doesn't overlap" is the easiest way to understand why we're flagging this error.

Open to suggestions on a better phrasing that is easier to understand in the general case, though.

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. labels Nov 27, 2024
@kirkwaiblinger
Copy link
Author

TBH, I haven't been able to get the error to trigger without providing an object literal in the comparison. That is to say,

// has TS errors.
// This comparison appears to be unintentional because the types '{}' and 'number' have no overlap.(2367)
// This condition will always return 'false' since JavaScript compares objects by reference, not value.(2839)
if ({} === 0) {
}

// no errors.
declare const oDeclared: {};
if (oDeclared === 0) {
}

// also no erorrs
const oLiteral = {};
if (oLiteral === 0) {
}

TS 2839 seems to be the more accurate and unambiguous error here. TS 2367 apparently doesn't generalize, since it doesn't get triggered when a literal isn't provided... which means that the only times it's triggered it's redundant with TS 2839 anyway. At least as far as I've been able to tell from experimentation.

If the above is a correct observation, my suggestion is - why not just remove TS 2367 from this case entirely, and just leave TS 2839?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

2 participants