jantimon
jantimon

Reputation: 38140

How do you type a class decorator in typescript?

What would be the correct way to write a class decorator which accepts only specific classes?

I tried the following:

class Component {
  age: number;
}

function registerComponent(name: string) {
  return <T extends Component>(constructor: T): T => {
    return constructor as T;
  }
}

@registerComponent("demo")
class C1 extends Component {

}

Which results in:

Argument of type 'typeof C1' is not assignable to parameter of type 'Component'.
  Property 'age' is missing in type 'typeof C1'.

Try in TypeScript Repl

Upvotes: 6

Views: 4008

Answers (1)

Duncan
Duncan

Reputation: 95652

What gets passed to the decorator is the type, not an instance of the type. Saying constructor: T means constructor must be an instance of type T, so instead you have to tell it that the parameter and the result are both constructors for the type T:

class Component {
  age: number;
}

function registerComponent(name: string) {
  return <T extends Component>(constructor: new () => T): new () => T => {
    return constructor;
  }
}

@registerComponent("demo")
class C1 extends Component {

}

and you would get an extra +1 for including the typescript repl if I could. Made it very easy to check my answer.

Note that you might also want to specify the constructor parameters.

Upvotes: 11

Related Questions