通用方法装饰器输入

时间:2018-05-12 09:11:14

标签: typescript

我正在尝试使foo通用装饰器符合MethodDecorator类型:

const foo: MethodDecorator = function <T extends Function = Function>(
    target: object,
    propertyKey: string | symbol,
    descriptor: TypedPropertyDescriptor<T>
): TypedPropertyDescriptor<T> {
    return {
        configurable: true,
        enumerable: false,
        value: descriptor.value!.bind(null)
    };
}

foo可以直接用作辅助函数,我更愿意选择另外输入它作为通用函数。

Here is错误:

Type '<T extends Function = Function>(target: object, propertyKey: string | symbol, descriptor: TypedPr...' is not assignable to type 'MethodDecorator'.
  Types of parameters 'descriptor' and 'descriptor' are incompatible.
    Type 'TypedPropertyDescriptor<T>' is not assignable to type 'TypedPropertyDescriptor<Function>'.
      Types of property 'value' are incompatible.
        Type 'T | undefined' is not assignable to type 'Function | undefined'.
          Type 'T' is not assignable to type 'Function | undefined'.
            Type 'T' is not assignable to type 'Function'.

foo如何符合MethodDecorator

1 个答案:

答案 0 :(得分:1)

似乎MethodDecorator不是generic type alias,因此无法缩小T类型。

type Foo<T> = (x: T) => T; // this one is generic
type Bar = (x: T) => T; // and this is not

这是有道理的,因为foo(即descriptor.value具有bind属性)中的假设通常不适用于MethodDecorator

由于type仅仅是别名,我们可以定义自己的。

type TypedMethodDecorator = <T extends Function>(
    target: Object,
    propertyKey: string | symbol,
    descriptor: TypedPropertyDescriptor<T>
) => TypedPropertyDescriptor<T> | void;

const foo: TypedMethodDecorator = function (target, propertyKey, descriptor) {
    return {
        configurable: true,
        enumerable: false,
        value: descriptor.value!.bind(null)
    };
}

class C {
    @foo
    m() {
        console.log('this:', this);
    }
}

new C().m(); // 'this: null'

由于类型推断,编译器知道foo是有效的装饰器。