Skip to content
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

Type of Unique symbol is lost for 2nd function overload #55101

Closed
vmatyi opened this issue Jul 21, 2023 · 9 comments
Closed

Type of Unique symbol is lost for 2nd function overload #55101

vmatyi opened this issue Jul 21, 2023 · 9 comments
Labels
Duplicate An existing issue was already created

Comments

@vmatyi
Copy link

vmatyi commented Jul 21, 2023

Bug Report

Type of a Unique symbol is lost (becomes non-unique) in "Overload 2 of 2" of a function declaration.
The same declaration compiles if it is the first overload.

🔎 Search Terms

Unique symbol, overload

🕗 Version & Regression Information

Tested multiple versions 3.3.3 through Nightly (5.2.0-dev 20230720)

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about unique symbol

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.1.6#code/MYewdgzgLgBAcgeQCoH0BiCCqcAiMC8MAygJ4C2ARiADYAUARIqhtjvQJQDcAUNwGYBXMMCgBLcDD4gQtPgC4YtdgQB8MaACdRYAObsFm7Ts4wA9KZgaApmRAA3IzCgALURBgATK8GoBDDb5i4AA0MCAa6gDuvgAOMY6Roi5Ozlbq3uAeYWBp9HyiAB5WEPQpaRBgojFWUPxCIuJgktKyCkqq6lBaujAAPk4k1SB88MjoWLj6nd06fTBCXvk5HjyCwkFNUjLyisr4aoY9-VCDVsOjzBM4U4ez-QtWS1ZZAN7cMDCgkLC+BJJKPA+1igAg0TV++EhF3GrBgAH55mBFtpnjAFL4eABfXhbWjtfbQliTHh1daNGAUfytXYdW5zE5DEZMGGTAxdRz3JGPFErUkNCSUjTU-EHdlHAaMwlXG5iu6I5HLGBvD5faAwCH-LjvSw1UHgghQ5lEvAIh5PLLorG8QV4vZqI3SkzmCn+T4gMjxajFdXuBB2KwaaggXxZACM3CAA

💻 Code

const NOT_FOUND = Symbol("NOT_FOUND");

function foo(f: () => string): string; // removing this declaration, or swapping with the second one "fixes" the snipet
function foo(f: () => string | typeof NOT_FOUND): string | undefined;
function foo(f: () => string | typeof NOT_FOUND): string | undefined {
const a = f();
return a === NOT_FOUND ? undefined : a;
}

foo(() => NOT_FOUND);

🙁 Actual behavior

No overload matches this call.
Overload 1 of 2, '(bar: () => string): string', gave the following error.
Type 'symbol' is not assignable to type 'string'.
Overload 2 of 2, '(bar: () => string | typeof NOT_FOUND): string | undefined', gave the following error.
Type 'symbol' is not assignable to type 'string | unique symbol'.(2769)
input.tsx(3, 37): The expected type comes from the return type of this signature.
input.tsx(4, 37): The expected type comes from the return type of this signature.

🙂 Expected behavior

Should compile, as the call matches the second overload (and removing the first overload actually fixes it)

@MartinJohns
Copy link
Contributor

MartinJohns commented Jul 21, 2023

Workaround: Add a type annotation. foo((): typeof NOT_FOUND => NOT_FOUND)

This seems to work as intended: #53753 (comment)

Unique symbols consistently follow the same widening rules as literals, which includes widening in places like non-consted arrays

You have the same issue when you use a literal like 1 instead of a symbol.

@vmatyi
Copy link
Author

vmatyi commented Jul 21, 2023

I'm not sure that explains different widening on the first overload, where it compiles in it's current form without a type annotation, than the second. (I can understand if that's life, but I didn't find any documentation/explanation on that)

Also, using const instead of the unique symbol is working without additional annotations, and according to #53753 (comment) the two supposedly behaves the same.

https://www.typescriptlang.org/play?ts=5.1.6#code/MYewdgzgLgBAcgeQCoH0BiCCqcAiMC8MArDAIYQyiRQDcAUHQGYCuYwUAluDIyCABSMAXDH4BKAgD4Y0AE4cwAczEi5CxTRgB6LTFkBTALYgAbuphQAFhwoATfcAA2pWaU7gANDBCyZAd1IAB0DzPw4rC0t9GQdwW28waIAiRg4AD30IJMjoiDAOQP0oJlZ2LjAePkERcSkZKHklGAAfCwBPQpBGeGR0LFwVesbFFphWe1TE23oWNncK3gFhUQl8aTUm1qgO-S6e1AxsHEGNkdbx-Un9eIBvOhhKcGgyAh5xegeDKGZZCtICfCERAHfp4AD8YzAEwU1xgIlI9AAvgxFvxamt9n0jmJ6EA

@MartinJohns
Copy link
Contributor

You don't have a second overload in your example.

@vmatyi
Copy link
Author

vmatyi commented Jul 21, 2023

Seems like I've reached my limits of understanding TypeScript terminology, but I'm referring to the bold line (which the error message refers as "Overload 2 of 2".

const NOT_FOUND = Symbol("NOT_FOUND");

function foo(f: () => string): string; // removing this declaration, or swapping with the second one "fixes" the snipet
function foo(f: () => string | typeof NOT_FOUND): string | undefined;
function foo(f: () => string | typeof NOT_FOUND): string | undefined {
const a = f();
return a === NOT_FOUND ? undefined : a;
}

foo(() => NOT_FOUND);

@MartinJohns
Copy link
Contributor

MartinJohns commented Jul 21, 2023

My mistake, I thought you referred to line 12-13 of your first playground as the second overload. Removing one of the overloads means you don't have any overload anymore and there's no overload resolution happening anymore.

@vmatyi
Copy link
Author

vmatyi commented Jul 21, 2023

If I swap the two, or add a third one and remove the first it compiles again, with overloads.

My initial claim is that the first and second overloads are behaving differently (and now an additional claim is unique symbol windening works differently than const widening)

@RyanCavanaugh
Copy link
Member

This is a duplicate of #241.

The contextual type for the return type of the function expression in this case comes from the first overload, since it's the first one that appears to match on arity. This means there's no contextual information to inform the processing of the NOT_FOUND return type to stay in its unwidened form, so the function return type is determined to be the wider form Symbol

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jul 21, 2023
@vmatyi
Copy link
Author

vmatyi commented Jul 21, 2023

Shouldn't symbol widening behave the same as with a literal?
const NOT_FOUND = false as const;
With a literal it compiles fine.

@typescript-bot
Copy link
Collaborator

This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Jul 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants