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

refinement types #7599

Open
zpdDG4gta8XKpMCd opened this issue Mar 20, 2016 · 12 comments
Open

refinement types #7599

zpdDG4gta8XKpMCd opened this issue Mar 20, 2016 · 12 comments
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript

Comments

@zpdDG4gta8XKpMCd
Copy link

This is a further development of the idea of tag types.

There are situations where being able to encode a certain predicate about a given value using its type is tremendously helpful.

Let's imagine that we have a number. In order to proceed with it we need to assert that it is greater than 0. This assertion doesn't come for free, because it takes some processor time to get evaluated. Since numbers are immutable this assertion only needs to be evaluated once and will hold true from then on without having to be reevaluated. But due to having no way to attach this knowledge to the number value we:

  • either need to play safe and reevaluate it every time immediately before using
  • or take our chances trying to trace it through the code from the place where it was asserted keeping the result of the assertion in mind and hoping not to break things during the next refactoring

Being able to attach additional knowledge to the type of a value in form of predicate that is guaranteed to hold true as long as the value doesn't change is what is called refinement types.

@ahejlsberg, what are the chances of seeing the refinement types in TypeScript one day?

References:

@zpdDG4gta8XKpMCd zpdDG4gta8XKpMCd changed the title refinment types refinement types Mar 20, 2016
@evmar
Copy link
Contributor

evmar commented Mar 21, 2016

In Rust this (or a similar?) idea was called typestate. This blog post discusses how you can sometimes model this using phantom types: http://pcwalton.github.io/blog/2012/12/26/typestate-is-dead/

@zpdDG4gta8XKpMCd
Copy link
Author

looks like it, my respects to the design team of rust

@mhegazy mhegazy added Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript labels Mar 28, 2016
@bennoleslie
Copy link

There seems to be a paper that describes an implementation of refinement types: https://scirate.com/arxiv/1604.02480

This seems to be the implementation: https://github.com/UCSD-PL/refscript

@ccorcos
Copy link

ccorcos commented Aug 10, 2017

Not sure if this helps but I think this might be related to Phantom Types as described here: https://medium.com/@gcanti/phantom-types-with-flow-828aff73232b

@denisw
Copy link

denisw commented Aug 25, 2017

Flow does have native support for phantom types in the form of Opaque Type Aliases:

https://medium.com/flow-type/hiding-implementation-details-with-flows-new-opaque-type-aliases-feature-40e188c2a3f9

Could this be a viable approach for TypeScript as well?

@KiaraGrouwstra
Copy link
Contributor

Guaranteeing non-0 input was one thing I found Idris language was doing to implement type-safe division, see here.
So rather than requiring the user to tag other types w.r.t. whether they might be zero, it infers it from the type. (As in TypeScript, type literals are a thing there.)

Within TypeScript, I've been experimenting to achieve something similar. I've been trying to implement this safe division as a PoC by using overloads to conditionally produce an error in type calls (#17961).
I've managed to get it to error on bad input (0), though I'm still working out a few quirks as discussed there.

Now obviously, this is approaching it from the other end -- putting the checks where the info is requested, rather than manually tagging a type from where it is supplied. For things like numbers the former approach feels sensible to me as the types could already bear the info available, though I'll admit marking the types instead does feel more sensible for cases like Rust's open file check.

@Zzzen
Copy link
Contributor

Zzzen commented Nov 23, 2017

Will Phantom Types be implemented?

@zalbia
Copy link

zalbia commented Aug 22, 2018

I use refined types in Scala and it is a godsend. I'm hoping this gets more attention.

@dead-claudia
Copy link

BTW, a refinement condition where x % 1 === 0 is necessary for all web APIs that accept unsigned long long and all JS APIs that perform ToInteger (including implicitly via ToLength). And for web APIs that use unsigned long/unsigned int/unsigned short/unsigned byte as well as JS APIs that do ToUint32/ToInt32/ToUint16/etc., those all require the additional constraint of 0 <= x && x < 2**32 and similar.

So for the web at least, refining numbers is absolutely critical to typing several APIs correctly.

@AnyhowStep
Copy link
Contributor

Couldn't the range as number type proposal also solve that problem?

#15480

There has been a proposal to have a min, max, and step for the range.


There's also a proposal for a type to just describe an integer type backed by a double type.

#28682

#30543

@dead-claudia
Copy link

@AnyhowStep Refinement types are a strict superset of the subset I was referring to. 😉

@nikeee
Copy link
Contributor

nikeee commented Jul 29, 2021

There are also IntervalTypes which address a similar issue: #43505

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests