在Typescript中创建通用方法装饰器

时间:2016-01-06 16:21:14

标签: generics types typescript decorator

在这段代码中,我试图让用户为通用装饰器函数fetchJson指定一个类型。

它会像这样工作:

  1. 用类似@fetchJson<User>
  2. 之类的东西装饰方法
  3. 然后我们将该函数替换为自动调用.then(res => res.json())的函数,并返回一个包含在Promise中的类型值。
  4. 我遇到的问题是我不知道如何将返回descriptor.value分配给用户指定的T. 有一个更好的方法吗?我觉得我完全错过了一些东西。

    interface PromiseDescriptorValue<T>{
      (...args: any[]): Promise<T>;
    }
    
    const fetchJson = <T>(
      target: Object,
      propertyKey: string,
      descriptor: TypedPropertyDescriptor<PromiseDescriptorValue<Response>> // Response is a whatwg-fetch response -- https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/whatwg-fetch/whatwg-fetch.d.ts#L58
    ): TypedPropertyDescriptor<PromiseDescriptorValue<T>> => {
      const oldMethod = descriptor.value;
    
      descriptor.value = function(...args: any[]) {
        return oldMethod.apply(this, args).then((res: Response) => res.json());
      };
    
      return descriptor;
    };
    
    
    // TS2322: Type 'TypedPropertyDescriptor<PromiseDescriptorValue<Response>>'
    // is not assignable to type
    // 'TypedPropertyDescriptor<PromiseDescriptorValue<T>>'. Type
    // 'PromiseDescriptorValue<Response>' is not assignable to type
    // 'PromiseDescriptorValue<T>'. Type 'Response' is not assignable to type 'T'.
    

1 个答案:

答案 0 :(得分:7)

也许是这样的:

interface PromiseDescriptorValue<T>{
  (...args: any[]): Promise<T>;
}

export function fetchJson<T>(): any
{
    return (
        target: Object,
        propertyKey: string,
        descriptor: any): TypedPropertyDescriptor<PromiseDescriptorValue<T>> => 
        {
        const oldMethod = descriptor.value;

        descriptor.value = function(...args: any[]) 
        {
            return oldMethod.apply(this, args).then((res: Response) => res.json());
        };

        return descriptor;
        };
}

class C 
{
    @fetchJson<User>()
    foo(args) 
    {
        //....
    }
}