Skip to content

Feature: type alternatives (to facilitate traits/mixins/type decorators) #727

Closed
@mindplay-dk

Description

@mindplay-dk

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixedA PR has been merged for this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions