Description
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:
class User {
public name: string;
}
interface Events {
on(event: string, callback: {():void});
// other methods here...
}
function addEvents<T>(object: T): T {
// decorate the object:
object['on'] = function() {
// ...
}
return <T> {};
}
var user = addEvents(new User());
The drawback here is you have to choose which is more important - that User
is still a User
after being decorated by addEvents()
, or that it is now also Events
. 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:
function addEvents<T>(object: T): T|Events {
// decorate the object:
object['on'] = function() {
// ...
}
return <T|Events> {};
}
var user = addEvents(new User());
The return type of the call is now User|Events
which is a distinct composite type composed members of User
and Events
.
The resulting composite type extends User
and implements Events
, 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?