GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||
GeezerVison is showing github.com — String literal types by DanielRosenwasser · Pull Request #5185 · microsoft/TypeScript Conversation
|
|
Very cool. Definitely seems highly desirable to find a way to do narrowing/type-guard sort of behavior here: type CardinalDirection = "North" | "East" | "South" | "West"; function move(distance: number, direction: CardinalDirection) { if(direction === "North") { // ok } else if(direction === "SouthWest") { // oops, no error at the moment } } |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Not that I want to sound negative but for every string literal, this gets called.
It's a huge slowdown.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
What kind of numbers are you seeing (and on what codebase)?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
If you consider that every string has on average 5 bytes, you're making 1-5 integer checks for every comparison:
I think the VM already optimize for this?
http://jsperf.com/string-vs-int-comparison-1
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
It's useless to speculate about what's fast and what's not. Measure it.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Meh. Measure it in 1 version of Chrome, it changes in the next. You measure it, I've said what I had to say.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Jon (@jbondc) 👍 for the benchmark test.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I don't think the original issue was so terrible. You only ran into this case when you were contextually typed by a type with a string literal constituent to begin with. In practice, this is not frequently encountered.
However, Jon (@jbondc), I think you'll like the the current implementation a lot better. We now only create a string literal type if the constituent types have a string literal type, not just if their content is equal.
Furthermore, the types are cached in a map of strings to string literal types. Whenever testing the assignability of two string literal types, reference equality kicks in (which is fast).
Additionally, error messages are slightly better because you have a specific literal type to report (i.e. Type '"Foo"' is not assignable to '"Bar"'. instead of Type 'string' is not assignable to '"Bar"'.).
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Jon (@jbondc) at worst that's probably much faster than trying to resolve the 100 different overloads. Though, I'm going to try to avoid speculating. I wasn't seeing a real perf hit in our benchmarks even with the initial change.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I assume that it was mentioned somewhere in thread and I didn't find it. Can I use string literal constraint for names of properties? I don't see that it works right now (playground) type Columns = 'name' | 'email' | 'age'; interface TableRow { [key: Columns]: string; } |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I'm really hoping to one day be able to quickly write ADTs in a succinct manner. something like this: Today, the compiler is unable to make the jump from |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
johnsoft we're looking into it, but right now we need to get a sense of how to make that play well with certain other language features. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Good to hear! Is there another issue I could follow that's more closely related to that use-case? I couldn't find anything after a quick search. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Also, #186. Duh. Can't believe I forgot about that one. In any case, I am waiting on some work where we'll be modifying the way we do type guards. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Great, thanks for the links! I'm really impressed with how the language is evolving. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
When i stumbled on this feature i found it a very welcome addition to the language, but after having played a little bit with it, and getting it not to work for everything it throwed at it, i wonder what this is really good for. const testFunc = (stuff:"bar")=>{}; testFunc("bar"); // OK const stuff = "bar"; testFunc(stuff);// not OK After two hours pulling my hair around this (my initial code was more complicated), i finally found out you have to write const stuff = "bar" as "bar"; Being no TS expert but just a normal programmer trying to gain time with the security of a type checking compiler, i find this overly counter-intuitive and complicated. Sorry if this not the place to discuss this, in the case would you be kind to point me to the correct place ? Thank you. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Vincent Jaubert (@vjau) this is expected behaviour. You are relying on type inference. And the infered type of |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
This is getting off topic - but yeah, I would expect the type of a |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Joe Wood (@joewood) it is discussed under #10195 and somewhat under #9489 which was closed because it would be a significant breaking change. Vincent Jaubert (@vjau) there is a better work around (also discussed in #9489) which is to be explicit about the type: const stuff: 'bar' = 'bar'; There are several types that are "TypeScript only" that don't get inferred, right now, literal types are one of those, tuples are another good example |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Kitson Kelly (@kitsonk) The issue in #9489 starts off by talking about the type literal of a const but switches to the issue of implicitly typing React style structures. As Anders Hejlsberg (@ahejlsberg) suggests in that issue, the type of a const could be narrowed to the literal type. I haven't seen a good example of where that would break existing code, unless I'm missing something. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
I didn't raise or respond to the issue... I am just pointing out that it addresses the bit off topic where you felt it wasn't being discussed elsewhere and might be a better place to continue the discussion. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Thanks Kitson Kelly (@kitsonk), I posted on that issue you referenced - #9489 (comment) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
See my response on the breaking change at #9489 (comment). Just to give some background, I'll write a little bit up here. After this PR went in, we heavily discussed an alternate approach of using widening to try to stop incorrect comparisons (e.g. The discussion started here: #6167 The problem is that too much of the time, the type would vanish too quickly or stick around too long. The behavior was looking generally inappropriate and every time we thought we had the perfect idea, it wasn't good enough for some other case. It became a game of whack-a-use-case. This original PR was nice because:
The comparability problem was solved with #5517 and #6196 anyway, so the only real issue is that people want it to be easier to infer literal types, which I absolutely get. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Thanks for the detailed response Daniel Rosenwasser (@DanielRosenwasser). In my mind a string literal type of one value is an immutable type, and it's paradoxical to assign that type to a mutable variable (at least, semantically). Implicit type inference for literals should therefore always widen when typing a mutable variable or parameter, and likewise an immutable variable should be narrowed as much as possible. It's a shame the #6554 couldn't be made to work, because it kind of seems counter-intuitive right now that a constant expression's type is different to its implicit type used for immutable binding. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Joe Wood (@joewood) it is not paradox, as long as they have the same type. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Felix Becker (@felixfbecker) right, but I mean it's essentially at that point semantically immutable. You can change its value to another string of the same value. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Changes Unknown when pulling ea4e21d on stringLiteralTypes into ** on master**. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.