我试图限制一个函数参数来扩展一个函数,其中参数和返回值被限制为相同的类型,而不要求函数本身是泛型的。
我有一个简单的工厂函数,它创建具有属性的dom节点,如下所示:
function div(className, attributes, children)EventListener属性(如onclick)被限制为函数或元组:
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。
发布于 2019-05-09 04:38:14
我坚持使用每个处理程序上的函数。在div函数上确保on*属性有一个元组,其中两个元素以您想要的方式关联,这是可能的,但不是以直接的方式。
它将涉及到捕获传递给div函数的对象文字的实际类型,并使用条件类型检查此自定义约束:
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]
});https://stackoverflow.com/questions/56048207
复制相似问题