-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Feature: type alternatives (to facilitate traits/mixins/type decorators) #727
Comments
A comment about the proposed syntax, |
I perceive e.g. Interestingly, you can use the To give a concrete example, if I type an argument as Compared with an argument typed as In cases where the
In other words, the difference is a conceptual (or in some languages run-time) aspect, not something you can distinguish at design-time or compile-time, and it doesn't matter whether you think of the operator as meaning "and" or "or", because, as far as static analysis is concerned, there's no difference. My guess is they picked It's possible they picked it simply for aesthetics too - since it doesn't really mean "and" anymore than it means "or", they may have picked it just because it's easier on the eyes ;-) |
If you wanted to avoid ambiguity by overloading, you could also choose a literal keyword operator, e.g. Come to think of it, it's probably premature to debate the syntax until we hear from the TypeScript team whether this is a feature they're even willing to consider. |
Appears to be similar to #14 but different from #186 which proposes sum types. I would prefer something simple and declarative, which does not leave a run-time footprint, to ensure semantic compatibility with JavaScript, in and out - especially in... there are tons of JS libraries already which decorate variables or prototypes with new members... |
Hitting this issue while using React mixins. I was wondering if Multiple Inheritance would work, which is how C++ does mixins. A sum type could be expressed as an anonymous type extending other types: function addEvents<T>(object: T): extends T,Events {
// decorate the object:
object['on'] = function() {
// ...
}
return <extends T,Events>object;
}
var user = addEvents(new User()); Unlike C++, order would matter here, with later entries overriding slots of previous entries. |
@joewood, they don't need to be
If an interface could be extend a type parameter, this would provide an alternative solution, more verbose, but also possible to be more type-safe:
|
OK this is not like #14 or #805, it's kind of the opposite. Here we need to say, in a generic way, "if you give me any object I will give you back the same object but now supporting a new interface", i.e. of both types so it is an intersection type not a union type. If interfaces could extend a type parameter this would solve the issue and enable expressing the traits pattern properly, as above. In the a real-world example we would want something like this (standard
Presumably it would also allow writing a type-safe .d.ts which did the same. |
@mindplay-dk , I think this is resolved by Intersection types #3622 committed to master 21 days ago. |
@benliddicott is correct. closing.. |
The type system does a great job at mirroring most type patterns in JS, all except mixins/traits, anything that decorates types - which unfortunately is very common in JS.
Without it the type system remains incomplete - that is, we're still one step short of being able to describe JavaScript mixin type patterns.
Duplication and interfaces are not the answer, because this does not reflect what's actually happening in JavaScript - e.g. not duplication, but type decoration of sorts. Not sure if I'm using the correct terminology here.
This small library is an example of a real-world decorator - duplicating all of it's method declarations in every single model type in a view-model hierarchy would be extremely impractical.
The following is a simplified example:
The drawback here is you have to choose which is more important - that
User
is still aUser
after being decorated byaddEvents()
, or that it is now alsoEvents
. There is no direct way to document this type pattern - your only option currently is to document the shape of the resulting type fully, duplicating all the member declarations contributed by the decorator.I propose syntax along the lines of the following, to support type alternatives:
The return type of the call is now
User|Events
which is a distinct composite type composed members ofUser
andEvents
.The resulting composite type extends
User
and implementsEvents
, and should pass type-checks for both.This should facilitate type-safe traits/mixins and probably other arbitrary type-patterns possible in JS.
Static type-hints with composite types are implemented in this way in e.g. PhpStorm using php-doc annotations, and it works well.
I think this may be a simpler and more flexible way to support mixins/traits, without explicitly adding support for those patterns specifically.
Thoughts?
The text was updated successfully, but these errors were encountered: