首页 > 解决方案 > 如何根据类方法返回类型声明参数类型?

问题描述

例如 :

    export const mock = <T>(provide, key: keyof T, value) => (){}
    class Service {
      do(): boolean {
        return true;
      }
    }
    // value have to be Boolean 
    mock<Service>(Service, "do", true)

value 参数是函数返回类型的类型T[key]。我想知道是否可以以某种方式声明值的类型。

标签: typescript

解决方案


这是我的解决方案:

/**
 * If T is a Class, return union string type of class methods
 */
type ClassType<T> = T extends { new(): infer R } ? keyof R : never

/**
 * Check if property is a function/method
 */
type AnyFunc = (...args: any[]) => any

export const mock = <P,>(provide: P, key: ClassType<P>, value: P extends { new(): infer R } ? R[keyof R] extends AnyFunc ? ReturnType<R[keyof R]> : never : never) => {}

class Service {
  do(): boolean {
    return true;
  }
}



const reuslt = mock<typeof Service>(Service, 'do', false) // ok
const reuslt2 = mock<typeof Service>(Service, 'foo', false) // error, expected do
const reuslt3 = mock<typeof Service>(Service, 'do', 42) // error, expected boolean

请记住,TS 以不同的方式对待Service类型typeof Service

因为,我不是解释大师,这是你的例子:

const x: Service = {
  do: () => true
}

const y: typeof Service = class {
  do() {
    return true
  }
}

TypeScript 类文档

更新 句柄承诺

/**
 * If T is a Class, return union string type of class methods
 */
type ClassType<T> = T extends { new(): infer R } ? keyof R : never

/**
 * Check if property is a function/method
 */
type AnyFunc = (...args: any[]) => any

type PromiseReturnType<T> = T extends Promise<infer R> ? R : T

export const mock = <P,>(provide: P, key: ClassType<P>, value: P extends { new(): infer R } ? R[keyof R] extends AnyFunc ? PromiseReturnType<ReturnType<R[keyof R]>> : never : never) => { }

class Service {
  do() {
    return new Promise<number>(resolve => resolve(42))
  }
}


const reuslt = mock<typeof Service>(Service, 'do', false) // ok
const reuslt2 = mock<typeof Service>(Service, 'foo', false) // error, expected do
const reuslt3 = mock<typeof Service>(Service, 'do', Promise.resolve(42)) // error, expected number
const reuslt4 = mock<typeof Service>(Service, 'do', 42) // ok

推荐阅读