sirisian / ecmascript-types

ECMAScript Optional Static Typing Proposal http://sirisian.github.io/ecmascript-types/
453 stars 4 forks source link

Possible function reflection extension and more decorator notes #68

Open sirisian opened 2 years ago

sirisian commented 2 years ago

One issue missing with parameter decorators in general and for types is the ability to get parameters information and types.

class A {
  f(x:uint32, ...y:uint32, z?:():void):string {
  }
}

Now, one could stringify and parse out parameters, but with decorators and such that would be brittle/insane. So a reflection would be expected for functions. I'd expect something similar to a property descriptors object except they're ordered, so an array.

Function.reflect(A.prototype.f);

The returned value would be an array in order to handle overloaded functions:

[
  {
    parameters: [
      {
        name: 'x',
        type: uint32,
        default: undefined,
        optional: false,
        rest: false
      },
      {
        name: 'y',
        type: []<uint32>,
        default: undefined,
        optional: false,
        rest: true
      },
      {
        name: 'z',
        type: ():void,
        default: undefined,
        optional: true,
        rest: false
      }
    ],
    return: {
      type: string
    }
  }
]

I could use this to build say a REST routing system connecting up basic type validation.

Would connecting metadata to this structure be intuitive? I think it would, but I'm not sure how well it would scale with interface types which also have decorators and such. Should work I believe.

const VALIDATIONS = Symbol();
function validate(validator) {
  return (value, context) => {
    if (kind === 'parameter') {
      let validations = context.getMetadata(VALIDATIONS) ?? [];
      validations.push(validator);
      context.setMetadata(VALIDATIONS, validations);
      return function(v:uint32):uint32 {
        return v;
      };
    }
  };
}

function f(
  @validate(x => x > 5)
  x:uint32
):void {
}
Function.reflect(f);
[
  {
    parameters: [
      {
        name: 'x',
        type: uint32,
        default: undefined,
        metadata: {
          VALIDATIONS: [x => x > 5]
        }
      }
    ],
    return: {
      type: void,
      metadata: {}
    }
  }
]