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

Runtime parameter info (name, optional, default) #8126

Open
yinso opened this issue Apr 17, 2016 · 5 comments
Open

Runtime parameter info (name, optional, default) #8126

yinso opened this issue Apr 17, 2016 · 5 comments
Labels
Domain: Decorators The issue relates to the decorator syntax Revisit An issue worth coming back to Suggestion An idea for TypeScript

Comments

@yinso
Copy link

yinso commented Apr 17, 2016

TypeScript Version:

1.8.9

Code

I'm trying to leverage decorators to create runtime contracts to check against incoming parameters.

Below is the ts code

class Foo {

  @contract
  test (a : integer, b : string) : boolean {
    return true
  }

  @contract
  testOptional (a : integer, b? : string) : boolean {
    return true
  }

  @contract
  testDefault (a : integer, b : string = 'hello') : boolean {
    return true
  }
}

The above generated the following Javascript.

var Foo = (function () {
    function Foo() {
    }
    Foo.prototype.test = function (a, b) {
        return true;
    };
    Foo.prototype.testOptional = function (a, b) {
        return true;
    };
    Foo.prototype.testDefault = function (a, b) {
        if (b === void 0) { b = 'hello'; }
        return true;
    };
    __decorate([
        contract, 
        __metadata('design:type', Function), 
        __metadata('design:paramtypes', [integer, String]), 
        __metadata('design:returntype', Boolean)
    ], Foo.prototype, "test", null);
    __decorate([
        contract, 
        __metadata('design:type', Function), 
        __metadata('design:paramtypes', [integer, String]), // same as above
        __metadata('design:returntype', Boolean)
    ], Foo.prototype, "testOptional", null);
    __decorate([
        contract, 
        __metadata('design:type', Function), 
        __metadata('design:paramtypes', [integer, String]), // same as above
        __metadata('design:returntype', Boolean)
    ], Foo.prototype, "testDefault", null);
    return Foo;
}());

Note that the three different ts functions generated the exact sets of __metadata calls. The design:paramtypes alone cannot distinguish whether a particular parameter is optional or has default values, and thus insufficient for building a runtime contract.

It would be great for TypeScript to support a full parameter info so decorators can be made more capable.

@yinso
Copy link
Author

yinso commented Apr 17, 2016

Also, it looks like the types provided for design:paramtypes don't work for the more complex types.

For example, a union type of integer | string generates [Object]:

  @contract
  testUnion(a : integer | string) : string {
    return 'hello';
  }

==>

    __decorate([
        contract, 
        __metadata('design:type', Function), 
        __metadata('design:paramtypes', [Object]), // integer | string
        __metadata('design:returntype', String)
    ], Foo.prototype, "testUnion", null);

And rest parameter just returns the type for the first position of the rest parameter, i.e. string[] becomes String:

  @contract
  testRest(a : integer, ...rest : string[]) : string {
    return 'hello';
  }

==>

    __decorate([
        contract, 
        __metadata('design:type', Function), 
        __metadata('design:paramtypes', [integer, String]), // string[] ==> String
        __metadata('design:returntype', String)
    ], Foo.prototype, "testRest", null);

@mhegazy
Copy link
Contributor

mhegazy commented Jun 2, 2016

The metadata provided are not meant to be a reflective runtime type system. you can find more discussion about this in #3060.

@mhegazy
Copy link
Contributor

mhegazy commented Jun 2, 2016

As for the optionality i think this fits into this model. we will have add a new key for the property. one thing to note, the decorator proposal for TC39 is undergoing some changes. we will not be taking on any decorator features until that stabilizes.

@canassa
Copy link

canassa commented Jun 17, 2020

👍 for including the optionality is the metadata information. Here is my use case for it:

I am building a configuration library that reads from several sources (environment variables, AWS SSM, etc). I use the decorators to identify how to fetch the attribute. e.g.:

class Config {
    @Env DB_PASSWORD!: string
}

The @Env reads the DB_PASSWORD type using the getMetadata function and I use its type to correctly parse the environment variable. Unfortunately, the metadata does not indicate to me if a field is marked as optional or not.

@mattvb91
Copy link

mattvb91 commented Mar 3, 2021

Currently have the same use case and need to see if a decorated class attribute is optional or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Domain: Decorators The issue relates to the decorator syntax Revisit An issue worth coming back to Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants