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

Prototype: Numeric Literal Types #7480

Closed
wants to merge 13 commits into from

Conversation

weswigham
Copy link
Member

This is a prototype for numeric literal types, in the same vein as string literal types.

All numeric syntaxes supported by JS should be supported (as far as I know) in type positions. Additionally, NaN and Infinity are builtin to the typespace as literal subclasses of number.

Also with this change:

  • The unary - operator gets contextually typed if its parent is contextually typed and it applies negation to any numeric literal type after it and returns the appropriate type. Ex: -(0x08) becomes -8.
  • Unary + and - is valid in type positions preceeding numeric literal types. Minus makes the following number into a negative number, as you may expect. (Plus is just allowed for symmetry and to clarify +Infinity)

There are tests testing guards against numeric literal types which I'll uncomment/add after #7235 is merged.

My open questions/thoughts:

  • I made it so NaN and Infinity have their respective types only when used in type positions. They are still of type number when used as values for compatibility reasons.
  • Comparability - I'd say that it's a given that we should allow comparisons of types akin to (1|3) < 2, but not assign them to one another incorrectly, it's safe to assume that this would need to use the comparable relationship reintroduced in Non-nullable types #7140. (Could also stand to add guards for numeric type unions on <=, <, >, >=) Even beyond that, if we know an enum member has the value 3, should it be assignable to a numeric literal type 2? Probably not. (Though it should likely still be comparable) I've started looking down the rabbit hole of comparing enum members with numeric literal types - it requires the introduction of the concept of another literal type associated with Enum Members to carry out effectively.
  • Unions of numbers and following the math - Right now, numeric types can flow through arithmetic operators - this is really cool (though it would be cooler if numbers were literal types by default). However, once they're inside a union, this flowing goes away. I could fix this really easily (just apply the arithmetic to all elements in the union, if both sides are unions of numeric types, then for each in each apply the arithmetic), but the downside is this is a really easy way to blow up the number of elements in a union.
  • Following the math is dicey in a nullable world - null acts as 0 in math, and undefined causes a NaN, so technically, all numeric literals after a math operation should be part of a union with NaN and the-result-if-one-or-both-parameters-is-zero. Which seems ridiculous and makes me want to just say that advanced literal types are only available in strict null mode.
  • Mutability and type safety - As with strings, mutability widening is probably a good idea for convenience... however, in addition to those measures, mutate-assignment patterns such as x += 2 where x is already of a literal type need to be disallowed (which is only an issue since I made arithmetic operators keep around numeric literal types), OR have their type updated to reflect potential new values (either widened like Mutability widening for literal types #6554 or redefined ala Control flow based type guards #6959).
  • Flowing numbers through generic parameters into inferred return values - This would make the type system able to act like a symbolic solver at compile time, which is neat. But this would need syntax for stating that a function can take some domain of numeric literal types (rather than just all subtypes of number or somesuch) as a parameter type.

I probably had more questions, but I want to put this out for people to see for now. This isn't something that should be considered ready to use, but it should be a great place to start looking at what's feasible.

@mhegazy
Copy link
Contributor

mhegazy commented Apr 5, 2016

thanks @weswigham. I have added this to the design meeting agenda; we have not had one in a while, so hopefully we should get to it within a couple of weeks. One thing to note, we have previously talked about how literal types fit in with enums; and that has been the main reason we held back on pushing more into literal types. I suspect this would be brought back to discussion with this proposal.

@DanielRosenwasser DanielRosenwasser added the Domain: Literal Types Unit types including string literal types, numeric literal types, Boolean literals, null, undefined label Apr 6, 2016
two = (((two ** two) - four) + (ten * two)) % three / two;


/*type True = 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this commented out?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are tests testing guards against numeric literal types which I'll uncomment/add after #7235 is merged.

@weswigham
Copy link
Member Author

@ahejlsberg I'm not sure if you've seen this or not - I know you're probably already working on the same thing. At the very least I've probably got some good tests here for you.

@ahejlsberg
Copy link
Member

@weswigham #9407 has now been merged, so I think we can close this one.

@weswigham
Copy link
Member Author

@ahejlsberg Agreed. The core feature from this PR has been implemented.

@weswigham weswigham closed this Jul 29, 2016
@weswigham weswigham deleted the number-types branch May 13, 2017 23:38
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Domain: Literal Types Unit types including string literal types, numeric literal types, Boolean literals, null, undefined
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants