-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Literal String Union Autocomplete #29729
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
Comments
From the compiler's point of view, this is just a very fancy way of writing You could write something like this: Naturally this doesn't stop you from writing |
Why not improve the compiler to keep more metadata around? |
It may accomplish the same behavior, but that's not intuitive to me at all. I doubt I could have gotten there on my own, and I know I would have trouble explaining it to someone newly coming to TS from JS. |
It would be great to have this built in, although understand it may be difficult to implement on the compiler. In the meantime, a generic workaround based on @RyanCavanaugh's solution might help: type LiteralUnion<T extends U, U = string> = T | (U & { zz_IGNORE_ME?: never })
type Color = LiteralUnion<'red' | 'black'>
var c: Color = 'red' // Has intellisense
var d: Color = 'any-string' // Any string is OK
var d: Color = { zz_IGNORE_ME: '' } // { zz_IGNORE_ME } placeholder is at the bottom of intellisense list and errors because of never
type N = LiteralUnion<1 | 2, number> // Works with numbers too |
Would be great if this could be implemented. It has the potential to improve even core Node.js APIs. The hash.digest |
Hey Guys type LiteralUnion<T extends U, U = string> = T | (U & {});
let x: LiteralUnion<"hello" | "world">;
x = "hey"; While this code is perfectly valid, "hello", and "world" are still showing up in the autocompletion. |
I noticed a problem with type guards using this hack: type LiteralUnion<T extends U, U = string> = T | (U & {});
function something(arg: LiteralUnion<'a' | 'b'>): 'a' {
if (arg === 'a') {
return arg; // Type '(string & {}) | "a"' is not assignable to type '"a"'
}
} Is there a way around this? |
I think I might have found a solution: Use a type like my type LiteralUnion<T extends U, U = string> = T | (U & {});
type UnpackedLiteralUnion<T> = T extends LiteralUnion<any, infer U> ? U : never
function something(arg: LiteralUnion<'a' | 'b'>): 'a' {
let unpackedArg = arg as UnpackedLiteralUnion<typeof arg>;
if (unpackedArg === "a") {
return unpackedArg;
}
else {
return "a";
}
} |
@AhmedElywa it's because you're using Here's the longer explanation: let x: (string & never); // x has type `never`
let y: number | (string & never); // y has type `number`
let z: ("Hello" | "world") | (string & never); // z has type `"Hello" | "world"` In order to get the solution to work you have to use How the solution workslet a: ("hello" | "world") | string; In this snippet let a: ("hello" | "world") | (string & {}); In this code-snippet Hope this helped you understanding. |
For those interested, there is a workaround for this called |
Is there a way to use this hack with the object key? |
yes, as a workaround you can use |
@mfulton26 it does not seem to work even with this helper. Adding both unions into a single string literal causes the whole thing to become just string. |
it works if you move the template literal type into |
If I'm understanding correctly, the reason the suggested solutions work is that a union of a primitive type and some variation of an empty object produces the wrapper/boxed object type corresponding to that primitive. For example, This prevents the union from getting reduced to the wider type, as the compiler will not reduce a literal to an object type. However, assignability is preserved, so we're still able to assign an arbitrary string value in this case. type Str1 = 'foo' | string;
// ^? string
type Str2 = 'bar' | String;
// ^? String | 'bar'
let a: Str2;
a = 'foo'; // 'foo' suggested via autocomplete
a = 'bar'; // arbitrary string does not error Is this the correct interpretation or am I making some incorrect assumptions along the way? |
Autocomplete works for literal string unions, but adding a union of
string
negates autocomplete entirely. This has been brought up before but I believe there is enough value in this feature to be reconsidered.My use case is to have a union of string literals for several colors, but also allow hex codes without having to add 16.7 million string literals.
TypeScript Version: 3.4.0-dev.20190202
Search Terms: Literal string union autocomplete
Code
Expected behavior:
Actual behavior:
Playground Link: https://stackblitz.com/edit/typescript-bwyyab
Related Issues: #12687 #13614
The text was updated successfully, but these errors were encountered: