簡體   English   中英

如何在 TypeScript 中使裝飾器類型安全?

[英]How do I make a decorator typesafe in TypeScript?

例子:

class Parent {
  parentMethod() {
    // ...
  }
}

@Hooks({
  // Only methods from the `Child` class (including inherited methods) must be allowed here
  childMethod: [/* ... */],
  parentMethod: [/* ... */]
})
class Child extends Parent {
  childMethod() {
    // ...
  }
}

@Hooks()裝飾器接受一個對象作為參數。 在這個對象中,鍵是來自Child類的方法名稱。 如何使@Hooks()裝飾器類型安全? 你能提供一個帶有@Hooks()類型的代碼示例嗎?

檢查這個是否適合你

interface ClassType<T> extends Function {
    new (...args: any[]): T;
}

type MethodKeys<T> = ({
  [K in keyof T]: T[K] extends Function ? K : never
})[keyof T]

type HooksOptions<T> = {
  [K in MethodKeys<T>]: []
}

function Hooks<T>(_options: HooksOptions<T>) {
  return function (ctor: ClassType<T>): ClassType<T> {
    return ctor
  }
}

class Parent {
  parentMethod() {
    // ...
  }
}

@Hooks<Child>({
  childMethod: [/* ... */],
  parentMethod: [/* ... */]
})
class Child extends Parent {
  childMethod() {
    // ...
  }
}

@Hooks("invalid-value") // error
class Child2 extends Parent {
  childMethod() {
    // ...
  }
}


@Hooks<Child3>({
  c: [], // error
  childMethod: [/* ... */],
  childMethod2: [/* ... */], // error
  parentMethod: [/* ... */]
})

class Child3 extends Parent {
  public c: string = ''
  childMethod() {
    // ...
  }
}

操場

打字稿中某個類的方法沒有類型(在其他語言中從未聽說過這種類型以及 TBH),您可以為函數簽名提供類型。

編輯:嗯,顯然有一些我不知道的技巧,如其他答案中所見..但如果你對快速簡單但有限的解決方案感興趣:

例如 :

let myAdd: (baseValue: number, increment: number) => number = (baseValue, increment) => baseValue + increment

此處鍵入函數的更多信息: https ://www.typescriptlang.org/docs/handbook/functions.html

如果這足以在裝飾器的聲明中使用類型簽名,如下所示:

Interface ObjectInterface {
   ChildMethods: {(param) => void} [], //or whatever fuction signature meets your need, this is just an example.
   ParentMethods: {(param) => void}[]
}

//this is the decorator declaration
function Hooks(obj: ObjectInterface) {
  return function (
    target,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) {
    // what ever implementation you have in hooks...
  };
}

這樣,當將非(param) => void類型的函數傳遞給裝飾器時,應該會導致編譯錯誤。

更多信息在這里: https : //www.typescriptlang.org/docs/handbook/decorators.html

在這里對於類型化函數數組,就像我在ObjectInterface所做的那樣: A Typed array of functions

我找到了解決方案

interface Type<T> extends Function {
    new (...args: any[]): T;
}

type HookMap<T> = {
  [func in keyof T]?: any[];
};

function Hooks<T>(hookMap: HookMap<T>) {
  return (clazz: Type<T>): void => {
    // ...
  };
}

class Parent {
  parentMethod() {
    // ...
  }
}

@Hooks({
  childMethod: [/* ... */],
  parentMethod: [/* ... */]
})
class Child extends Parent {
  childMethod() {
    // ...
  }
}

操場

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM