[英]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.