Description
Open String Union for Auto-Complete
-
People want to be able to write
string | "foo" | "bar
- Can assign any string, but writing out a literal string when contextually typed or compared against would give completions for
"foo"
and"bar"
.
- Can assign any string, but writing out a literal string when contextually typed or compared against would give completions for
-
Problem is that this is just reduced to
string
-
The hack today is to write
(string & {}) | "foo" | "bar
where(string & {})
is recognized as a tagged string (which itself is a load-bearing hack for primitive subtypes/newtype primitives), and not reduced away. -
One idea was to push this into JSDoc if it's just for tooling - something like
/** @suggest {...} */
-
Maybe not good enough - you want to compose these.
type Color<T extends string> = T | ... | (string & {});
- Where would you put the comment there? Aliases aren't always propagated around as you'd want.
-
Last time this was discussed, we weren't sure - is this a thing specific to declaration sites, or do we need a thing specific to the type system?
-
After revisiting, we want to ask - what is wrong with the hack?
- It was annoying to us - the hack is an incoherent type.
- Annoying to new users because it's not discoverable.
-
On "it's an incoherent type" - what can you possibly do? As the editor's note points out above, it's a load bearing hack for primitive subtypes. Every time we accidentally stop supporting them, we have to restore it.
-
We tell people "this works" - if you want them to stop doing this, you need to create the better thing.
-
A lot of the examples really could
/** @suggest {...} */
-
Part of why we revisited this again was because we wanted to move
NonNullable
to beT & {}
. -
We don't mind the
& SomeSortaThing
, but we don't like people using& {}
. -
Conclusion?
- Unclear if we want to pursue a nominal tag, a built-in type, prescriptive guidance, or a JSDoc technique.
- And even if we pick one, it's not clear if we can get rid of the existing solutions today.