Typescript Decorator函数通用类型

问题描述

我正在创建Express rest API,也正在研究创建自己的装饰器函数。我现在正在为控制器类创建一个装饰器。

但是每当我想将此装饰器添加到控制器时,都会出现以下错误

Unable to resolve signature of class decorator when called as an expression. Type 'Constructable' is not assignable to type 'typeof ZoneController'. Property 'getZones' is missing in type 'RestController' but required in type 'ZoneController'.

错误不会在stackblitz中弹出(它应该在ZoneController的装饰器上弹出),但是有关代码,请参见Stackblitz

这很有意义,因为RestController是ZoneConroller的父类,因此它不知道任何方法。为了解决这个问题,我想向控制器装饰器添加一个通用类型:

type Constructable<T> = new (...args: any[]) => T

export function Controller<T extends RestController>(restCtor: Constructable<T>): Constructable<T> {
  return class extends restCtor {
    router = null
  }
}

但这会导致以下错误

Class '(Anonymous class)' incorrectly extends base class 'T'. '(Anonymous class)' is assignable to the constraint of type 'T',but 'T' Could be instantiated with a different subtype of constraint 'RestController'

我不知道该如何解决错误。有关错误代码,请参见以下Stackblitz。 我已经找到了有关此错误的一些文档(herehere),但我不清楚如何更改代码解决错误

我应该如何更改代码解决此问题? 我正在使用打字稿v4.0.2和以下TSConfig

{
  "compileOnSave": false,"compilerOptions": {
    "baseUrl": "./","outDir": "./dist/out-tsc","sourceMap": true,"declaration": false,"downlevelIteration": true,"experimentalDecorators": true,"module": "esnext","moduleResolution": "node","importHelpers": true,"target": "es2015","typeRoots": [
      "node_modules/@types"
    ],"lib": [
      "es2018","dom"
    ]
  }
}

解决方法

可以使用接口编写类的定义:

interface SomeClass {
  new(...args: any[]): SomeClass
}

按照相同的模式,我认为您想更改Constructable的定义:

type Constructable<T> = new (...args: any[]) => Constructable<T>