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

Combine few classes in one with decorators #8876

Closed
SET001 opened this issue May 28, 2016 · 1 comment
Closed

Combine few classes in one with decorators #8876

SET001 opened this issue May 28, 2016 · 1 comment
Labels
Question An issue which isn't directly actionable in code

Comments

@SET001
Copy link

SET001 commented May 28, 2016

Recently I was playing with TypeScript decorators and ended up with interesting pattern. It is possible to extend some basic class with any number of other classes. The idea is to extend decorated class prototype with prototypes of classes from decorator. This is somehow different from traditional class inheritance. It is more like adding plugins:

So here is the example decorator which extends some class with plugins:

export function Plugins(plugins: any[]): any{
  return function(target: any){
    var layer = function(){};
    layer.prototype = target.prototype;
    for (var plugin of plugins){
      _.extend(layer.prototype, plugin.prototype);
    }
    return target;
  }
}

Now let's say we have class that handles connection. Something like this.

export class SocketIOClientConnection extends ConnectionLayer{
    constructor(public socket?: SocketIO.Socket){}

    send(message: string){
        this.socket.emit(message);
    }

    broadcast(message: string){
        this.socket.emit(message);
    }
    disconnect(){}
}

and imagine that all socket events are somehow binded to this class methods which begin with on. Then we can decorate this connection class with some plugins which would add handlers of some sort. We can have auth, chat, streamer and as many plugins we ever want.

export class AuthConnection extends ConnectionLayer{
    onLogIn(login?: string, password?: string){
        this.socket.send('loggedOn');   
    }
    onLogOut(){
        this.socket.send('loggedOut');
    }
    onRegister(){}
}

we can decorate connection method it this way

@Plugins([AuthConnection])
export class SocketIOClientConnection extends ConnectionLayer{

and now it will be able to handle login requests... The goals of this approach is that auth implementation know nothing about how exactly connection handled. We can have socketIO or webRTC or whatever class implementing some interface and decorated with this auth plugins.

Now few questions:

What do you think about this approach?
Is it ok to use decorators in this way?
Maybe this pattern already exist and have some name? any readings on this?
What pitfalls this approach have? (for example, plugins can not have methods with same name and so on)

@kitsonk
Copy link
Contributor

kitsonk commented May 28, 2016

This isn't always the best forum for general TypeScript discussion. StackOverflow, gitter or #typescript on IRC are usually better.

Any mutations to make to the prototype are not reflected in the classes types. There are a few discussions about programmatically modifying the types (see #4490), but nothing yet delivered, although it will likely be delivered via ambient decorators in TS 2.1 (see #2900).

Angular 2 makes heavy use of decorators in creating its components, though, as mentioned, since changes to the prototype are not reflected in the type information about the class, it is generally limited to assigning/mutating values of the prototype.

Decorators are not a "TypeScript" thing. They are essentially an implementation of the Stage 1 proposal of ECMAScript Decorators.

@mhegazy mhegazy closed this as completed Jun 7, 2016
@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label Jun 7, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

3 participants