首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Typescript generics -将函数参数和返回类型限制为相同的类型,并根据使用情况推断类型

Typescript generics -将函数参数和返回类型限制为相同的类型,并根据使用情况推断类型
EN

Stack Overflow用户
提问于 2019-05-09 04:00:32
回答 1查看 917关注 0票数 0

我试图限制一个函数参数来扩展一个函数,其中参数和返回值被限制为相同的类型,而不要求函数本身是泛型的。

我有一个简单的工厂函数,它创建具有属性的dom节点,如下所示:

代码语言:javascript
复制
function div(className, attributes, children)

EventListener属性(如onclick)被限制为函数或元组:

代码语言:javascript
复制
type EventHandler<T extends Event> = ((ev: T) => void) | [(ev: T, seed: SameType) => SameType, SameType];

其中SameType基本上注释了您应该提供一个元组,其中第一项是一个接受种子值的函数,第二个参数指定在调用函数时传递给函数的初始种子。

我试图使参数本身成为泛型,将其自身传递给一个类型,然后使用条件匹配,但没有成功。我不能在接口本身使用泛型,因为那是没有意义的(onclick、oninput和onmouseover都有不同的SameType种子值)。

这个函数的灵感来自于Inferno的linkEvent函数(https://github.com/infernojs/inferno/blob/master/packages/inferno/src/core/types.ts#L45),但它并没有调用一个你只需要传入一个元组的函数,我认为这个元组很方便,但是输入它却是一场噩梦!感谢您提供的任何意见。

这个问题是与Typescript不允许值级别的泛型有关,还是我遗漏了什么?我在想this issue

EN

回答 1

Stack Overflow用户

发布于 2019-05-09 04:38:14

我坚持使用每个处理程序上的函数。在div函数上确保on*属性有一个元组,其中两个元素以您想要的方式关联,这是可能的,但不是以直接的方式。

它将涉及到捕获传递给div函数的对象文字的实际类型,并使用条件类型检查此自定义约束:

代码语言:javascript
复制
function div<TAttr extends {
  onClick:EventHandler<MouseEvent>,
  onKeyDown:EventHandler<KeyboardEvent>
}>(attributes: TAttr & CheckAttr<TAttr>): TAttr {
  return attributes;
}

type UnionToIntersection<U> = 
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never

type CheckAttr<T> = UnionToIntersection<CheckAttrHelper<T>[keyof T]> 
type CheckAttrHelper<T> = {
  [K in keyof T]:
    T[K] extends [(ev: Event, seed: infer P) => infer R, infer S] ?
      ([R] extends [P] ? [S] extends [P] ? never
          : Record<K, "Seed type is not assignable to parameter type">
          : Record<K, "Return type is not assignable to parameter type">
      ): never
}

type EventHandler<T extends Event> = ((ev: T) => void) | [(ev: T, seed: any) => any, any];

//ok
let a = div({
  onClick: [(ev, n: string | number) => 2, "1"],
  onKeyDown: [(ev, n: number) => n + 1, 1]
});

//err 
// Type '(string | ((ev: MouseEvent, n: string) => number))[]' is not assignable to type 
//'[(ev: MouseEvent, n: string) => number, string] & 
// "Return type is not assignable to parameter type"'.
let a2 = div({
  onClick: [(ev, n: string) => 2, "1"],
  onKeyDown: [(ev, n: number) => n + 1, 1]
});
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56048207

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档