打字稿:对通用

时间:2018-04-08 07:31:47

标签: typescript generics constraints

我有包含功能的对象:

const messages = {
  helloYou: (name: string) => `Hello ${name}`,
  goodbye: () => 'Good bye',
}

以及管理此类对象的类:

class MyClass<T> {
  …
  getMessage<K extends keyof T>(name: K): T[K] {
    …
  }
  …
}

然后我可以输入安全调用类中注册的对象的函数:

myObject = new MyClass<typeof messages>(messages)
myObject.getMessage('helloYou')('John')
myObject.getMessage('goodbye')()

问题是getMessage正在返回一个函数,如果我不需要参数(比如上面的goodbye示例),我可能会忘记空括号。所以我尝试编写一个函数,同时获取消息名称和参数。这就是我设法做的事情:

export function t<O extends Messages & { [P in K]: (arg1: P1) => string }, K extends keyof O, P1>(myObject: MyClass<O>, name: K, p1: P1): string

(这个函数当然是为0,2,3,4 ...函数参数重载)

此功能以这种方式使用:

t(myObject, 'helloYou', 'John')

这样做效果很好且类型安全,但我希望此方法tMyClass的方法,而不是将myObject作为每个调用的第一个参数。这样称呼它确实会更优雅:

myObject.t('helloYou', 'John')

但是,正如您在方法t中看到的那样,我设法将约束放在对象类型O上(对应于T中注册的对象类型MyClass )取决于其他功能参数。如果我希望t成为类方法,我需要反转约束,即约束O上的其他参数。

有没有人知道这样做的方法?

谢谢。

1 个答案:

答案 0 :(得分:1)

您应该可以使用this parameters完成目标。如果为函数<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>命名第一个参数并为其指定类型,则会将该函数体中的this类型约束为该类型。正如使用参数类型与参数的类型注释不匹配的函数调用函数一样,在类型与方法&#39; s {不匹配的对象上调用方法是错误的。 {1}}参数注释。

在您的情况下,请采用表单

的每个函数签名(重载和实现)
this

并将其转换为方法,方法是将其放在类定义中,并用this参数替换function t< O extends Messages & { [P in K]: (arg1: P1) => string }, K extends keyof O, P1> (myObject: MyClass<O>, name: K, p1: P1): string; 参数:

myObject

新方法的行为应与独立功能相同。也就是说,this当且仅当public t< O extends Messages & { [P in K]: (arg1: P1) => string }, K extends keyof O, P1> (this: MyClass<O>, name: K, p1: P1): string; 是错误时才应该是错误。试试看。希望有所帮助;祝你好运!