在Typescript中检测方法签名?

时间:2018-08-08 19:27:25

标签: javascript typescript

假设我们有这样的东西:

    class TodoStore {
      query(state:State):Array<Observable<any>> {
        return state.getAll(); //Custom implementation
      }
    }

在运行时,我想找到所有以State作为第一个参数的方法,以便可以通过传入state参数的函数来包装这些方法。 Typescript可以吗?

包装器类将大致像这样工作:

class TodoStoreWrapper {
    constructor(private state:State);
    todoStore: TodoStore = new TodoStore();
    query() {
        todoStore.query(state);
    } 
}

1 个答案:

答案 0 :(得分:1)

虽然在运行时我们没有类型信息来查找哪些函数具有状态参数,但是我们可以在编译时创建一个类型,该类型的结构要求我们在对象常量中指定所有具有第一个方法的方法状态类型的参数。尽管此方法确实需要我们指定方法,但它是安全的,因为如果我们忘记了一个方法,编译器将抛出错误,如果指定的名称不是该方法,则编译器也会抛出错误。

我们还可以将其与从具有状态参数的所有方法中删除状态参数的类型组合起来:

class TodoStore {
    query(state: State): Array<Observable<any>> {
        return state.getAll(); //Custom implementation
    }
    queryWithParam(state: State, p:string): Array<Observable<any>> {
        return state.getAll(); //Custom implementation
    }
}

type StateMethods<T> = Record<{
    [P in keyof T]: T[P] extends ((s:State, ...a:any[])=> any) ? P : never
}[keyof T], true>

type Wrapped<T> = {
    [P in keyof T]:
    T[P] extends ((s: State, ...a: infer A) => infer R) ?
        (...a: A) => R :
        T[P]
}

function createWrapper<T>(toWrap:T, methods: StateMethods<T>): Wrapped<T>{
    return null as any;
}

let w = createWrapper(new TodoStore(), { // This object will be checked by the compiler to contain the keys of all relevant methods 
    query: true,
    queryWithParam: true 
});

w.query()
w.queryWithParam("")

也可以使用装饰器方法,您应该查看哪种方法更适合您的用例,但是这种方法也可以工作。

Playground link