typescripttypescript-decorator

The `ClassDecorator` type defined in `tc39/proposal-decorators` is not applicable without TypeScript errors


I got the error

TS1270: Decorator function return type 'void | Function' is not assignable to type 'void | typeof ReactiveStateExperimentalSample'.

  Type 'Function' is not assignable to type 'void | typeof ReactiveStateExperimentalSample'.

    Type 'Function' is not assignable to type 'typeof ReactiveStateExperimentalSample'.        Type 'Function' provides no match for the signature 'new (): ReactiveStateExperimentalSample'.

when tried to apply the decorator

const VueComponentOptions: (
  value: Function,
  context: {
    kind: "class";
    name: string | undefined;
    addInitializer(initializer: () => void): void;
  }
) => Function | void = (
  value: Function, context: ClassDecoratorContext
): Function | void => {

  const vueOptions: ComponentOptions = {
    methods: {},
    computed: {}
  };

  return defineComponent(vueOptions);

};

to class

@VueComponentOptions
export default class ReactiveStateExperimentalSample {

}

According tc39/proposal-decorators, the signature of class decorator is

type ClassDecorator = (value: Function, context: {
  kind: "class";
  name: string | undefined;
  addInitializer(initializer: () => void): void;
}) => Function | void;

There is no such type in TypeScript 5 (more exactly, in typescript/lib/lib.decorators.d.ts). There is such type in typescript/lib/lib.decorators.legacy.d.ts but legacy is legacy.

Am I doing something wrong or it is just immature API? TypeScript 5 is not the beta anymore, thus "experimental decorators" is not experimental anymore.


Solution

  • TS decorators are not fully TC39-compatible yet

    // logs [class X{}]
    @((...a) => console.log(a))
    class X {}
    

    https://www.typescriptlang.org/play?experimentalDecorators=true&ts=5.1.0-dev.20230402#code/PTAEBsHsHMGdQNoGNwENbwBoG8C+BdAKAAEAKUgOitQEpQBeAPlCUgDtZJwBTCqaUrRqEU6LKDyEgA

    So meanwhile your decorators should follow the current typings

    // lib.es5.d.ts
    declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
    declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
    declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
    declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;