-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Literal string types downgraded to string
at generic function call (which doesn't happen with a mixed type!)
#40377
Comments
declare function compare<T, U>(a: T, b: T & U): boolean; Should get the behaviour you're looking for from declare const words: 'hello' | 'world';
declare function compareStrings<T extends string>(a: T, b: T): boolean;
compareStrings(words, ''); // No error and T is inferred as "" | "hello" | "world" Same also happens if you use Update |
@robbiespeed Wow, it really works!! Wonderful! May I ask why it works? And what was your thought process to arrive at this solution?
Hmm, how do you know it is expected? |
By using two generic parameters, you can guarantee that the type of declare function compare<T, U extends T>(a: T, b: U): boolean;
While I am not 100% certain, it does make sense when you look at in the sense that inference is a method of finding a common type for
declare function compare<T>(a: T, b: T): boolean;
compare({ foo: true }, { bar: true }); // T is { foo: boolean; bar?: undefined; } | { bar: boolean; foo?: undefined; }
compare(1, 2); // T is number
compare(1 as const, 2 as const); // T is 1 | 2
compare('a', 'b'); // T is string
compare('a' as const, 'b' as const); // T is 'a' | 'b' This all work the same down to version 3.3, with the exception of the |
@robbiespeed I see! Nice. Very clever!! Thank you!!
Thanks, everything you said makes sense, especially the part where you compare using and not using |
That part seems a bit strange to me as well. I would suggest leaving this issue open, and hopefully someone on the Typescript team has an answer. |
The desired behavior here is very much context-dependent, and as such there are special rules around unions of literals of a common base type. |
@RyanCavanaugh is there anywhere in the handbook that describes the rules? Would be nice to have somewhere to point to that avoids confusion on what is intended behaviour. |
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
@RyanCavanaugh I would like to know these special rules better too :) |
TypeScript Version: 4.0.2
Search Terms: literal string type, mixed union type, generic function call, type inference
Code
Expected behavior:
Argument of type '""' is not assignable to parameter of type '"hello" | "world"'.
'hello' | 'world'
when pressing Ctrl+Space at the empty string there.Actual behavior: No error and no autocomplete.
Playground Link
Related Issues: #38968 (cc @mmkal)
The text was updated successfully, but these errors were encountered: