deprecates Identity
- use newtype
instead
#167
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
changelog
It also re-names
Identity
tonewtype
, to give users a signal as to its intended purpose.new features
string.literal
string.decodedURI
string.encodedURI
string.decodedURIComponent
string.encodedURIComponent
deprecations
This release adds a handful of "newtypes". These newtypes behave a bit differently than branded or flavored types, since they (in the examples that this PR introduces) are simply interfaces that wrap the native
string
type.This is accomplished by wrapping the naked type parameter in a wrapper function called (in this library)
id
.id
is just the identity function: it simply gives back what its given.Now that we have
newtype
, we can implementstring.literal
:Notice that **we're not passing the
type
parameter tonewtype
. We're passing the universal string type (string
).By doing that, we're choosing a prototype that values with this type should have available.
To make this type more useful, we override the
toString
andvalueOf
methods, so that they return the narrowed type oftype
.There! We've now implemented a custom
string
type, and overridden one of its methods,toString
, to return a custom type.All of its behavior is the same; all we've done is told the TS compiler that we want it to track some extra information at the typelevel.
We could take this further -- I'm not sure yet if this is a good idea or not, but for completeness, let's try overridding
String.prototype.concat
:Notice that we're re-wrapping the output in
string.literal
, that way we can continue concatenating if we wanted without having to re-wrap the output instring.literal
.Here's what using it looks like:
That's awesome. Until today I didn't know this kind of thing was possible in the TypeScript type system -- as far as I know, this kind of thing isn't being done anywhere else (but I'd love to hear about it if you know of other libraries doing this!).
One last problem we need to take care of.
When we override
String.prototype.concat
, we get a new TypeError:This TypeError actually makes sense: in fact, that's the whole reason we're creating these
newtypes
, is so that the type system can tell the difference between a string and the new type that we're creating.In this case though the TypeError is undesirable, since we're intentionally overriding its type-level behavior.
How can we get our new concat to play nice with the global
String
prototype?The trick is to simply say that we don't want to use
String.prototype.concat
's type signature at all:And with that, we've implemented a new type whose type-level behavior inherits from the native
string
type, but preserves type information even while concatting.I hope these release notes were useful, or at least interesting, and as always, thanks for keeping an open mind as we explore these things together.