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

Decorated classes should implement the decorator return type. #5627

Closed
pietschy opened this issue Nov 12, 2015 · 3 comments
Closed

Decorated classes should implement the decorator return type. #5627

pietschy opened this issue Nov 12, 2015 · 3 comments
Labels
Duplicate An existing issue was already created

Comments

@pietschy
Copy link

This is strongly related to #4881 but I'm not sure if it's feature request or if it's really a bug. Given that the Decorators spec states the decorator can return a new constructor function, it sort of seems like it should work.

The following example uses constructor function types and very nearly works.

View this in playground

interface ConstructorFunction<T> {
    new (...args:any[]):T;
    prototype:T
}

interface Disappearing {
    isVisible():boolean;
    vanish():void;
}

function Disappearing<T>(ctor:ConstructorFunction<T>):ConstructorFunction<T & Disappearing> {
    let result = <ConstructorFunction<T & Disappearing>>ctor;
    result.prototype.isVisible = () => {
        return !this['_hasDisappeared'];
    };
    result.prototype.vanish = () => {
        this['_hasDisappeared'] = true;
    };
    return result;
}

// This seems like it should work
// @Disappearing
// class Cat {
//     constructor(private name:string) {}
// }

// but I have to do this
@Disappearing
class Cat implements Disappearing {
    constructor(private name:string) {}
    isVisible() {return false}
    vanish(){}
}

// let ctor = wrappedBlah(Cat);
let buster = new Cat('Buster');
alert(`Is Buster visible? -> ${buster.isVisible()}`);
buster.vanish();
alert(`Is Buster visible? -> ${buster.isVisible()}`);
@mhegazy
Copy link
Contributor

mhegazy commented Nov 12, 2015

The issue here is that the tyep system is not aware of any type mutations the decoarator does to the original type. #4881 tracks supporting this. This issue is a duplicate of #4881.

for your scenario. you use interface/class merging to get what you want:

@Disappearing
class Cat {
    constructor(private name:string) {}
}

interface Cat extends Disappearing {}

let buster = new Cat('Buster');
buster.vanish();

@mhegazy mhegazy closed this as completed Nov 12, 2015
@mhegazy mhegazy added the Duplicate An existing issue was already created label Nov 12, 2015
@pietschy
Copy link
Author

Thanks @mhegazy,

I guess I was hoping this scenario was different since the decorator return types were explicitly defined by the function parameters and return types.

@mhegazy
Copy link
Contributor

mhegazy commented Nov 12, 2015

i agree that this is helpful, but that is #4881.

@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
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants