输入重载的 class 方法
Typing an overloaded class method
我需要围绕按参数类型重载的方法 foo
编写一个包装器。
更新:A
扩展 B
更新 2:TS playground link
const getFoo: {
foo(x: number, y?: A): A;
foo(x: number, y?: B): B;
}
在我启用了 TS IntelliSense 的 IDE 中,const a = foo(1, {} as A)
是 A
类型,const b = foo(1, {} as B})
是 B
类型。所以,重载正在工作。
我的包装函数:
const fooWrapper = () => {
const { foo } = getFoo();
return {
modifiedFoo: <T extends A | B>(x: number, y?: T) => {
// my code
return foo(x, y);
}
}
但是,const c = modifiedFoo(1, {} as A)
是 B
类型,而不是您期望的 A
。
正在尝试将 return 类型添加到 modifiedFoo
:
modifiedFoo: <T extends A | B>(x: number, y?: T):
T extends A
? A
: T extends B
? B
: never
修复了 modifiedFoo
的 return 类型,但它在 return foo(x, y)
行的 modifiedFoo 定义中导致编译器问题,声明
Type 'B' is not assignable to type 'T extends A ? A : T extends B ? B : never'
Type 'A' is not assignable to type 'T extends A ? A : T extends B ? B : never'
对我来说很奇怪,我可以调用 return foo(x, y as A)
让 modifiedFoo
总是 return A
,或者 return foo(x, y as B)
得到 modifiedFoo
总是 return B
,但是泛型 returnFoo(x, y)
y 是类型 T
不是 return 正确的类型,除非我添加明确的 return 导致编译器错误的类型定义。
回答并说明:
type OverloadedParams<T> = T extends { (...o: infer U1): any; (...o: infer U2): any } ? U1 | U2 : never;
type OverloadedReturn<T, U> = Extract<
T extends {
(...args: infer A1): infer R1;
(...args: infer A2): infer R2;
} ? U extends A1 ? [U, R1] : U extends A2 ? [U, R2] : never : never, [U, any]
>[1];
const gWrapper = () => {
const { foo } = getG();
return <T extends OverloadedParams<G["foo"]>>(...args: T): OverloadedReturn<G["foo"], T> => {
return foo(args[0], args[1]);
}
}
关键是获取重载参数类型(而非子类型)的父类型,并使用重载函数的定义将其与适当的 return 类型相关联。
我仍然不明白,为什么花了这么长时间才解决,是为什么
type OverloadedReturn<T, U> = T extends {
(...args: infer A1): infer R1;
(...args: infer A2): infer R2;
} ? U extends A1 ? R1 : U extends A2 ? R2 : never : never;
无效。
我需要围绕按参数类型重载的方法 foo
编写一个包装器。
更新:A
扩展 B
更新 2:TS playground link
const getFoo: {
foo(x: number, y?: A): A;
foo(x: number, y?: B): B;
}
在我启用了 TS IntelliSense 的 IDE 中,const a = foo(1, {} as A)
是 A
类型,const b = foo(1, {} as B})
是 B
类型。所以,重载正在工作。
我的包装函数:
const fooWrapper = () => {
const { foo } = getFoo();
return {
modifiedFoo: <T extends A | B>(x: number, y?: T) => {
// my code
return foo(x, y);
}
}
但是,const c = modifiedFoo(1, {} as A)
是 B
类型,而不是您期望的 A
。
正在尝试将 return 类型添加到 modifiedFoo
:
modifiedFoo: <T extends A | B>(x: number, y?: T):
T extends A
? A
: T extends B
? B
: never
修复了 modifiedFoo
的 return 类型,但它在 return foo(x, y)
行的 modifiedFoo 定义中导致编译器问题,声明
Type 'B' is not assignable to type 'T extends A ? A : T extends B ? B : never'
Type 'A' is not assignable to type 'T extends A ? A : T extends B ? B : never'
对我来说很奇怪,我可以调用 return foo(x, y as A)
让 modifiedFoo
总是 return A
,或者 return foo(x, y as B)
得到 modifiedFoo
总是 return B
,但是泛型 returnFoo(x, y)
y 是类型 T
不是 return 正确的类型,除非我添加明确的 return 导致编译器错误的类型定义。
回答并说明:
type OverloadedParams<T> = T extends { (...o: infer U1): any; (...o: infer U2): any } ? U1 | U2 : never;
type OverloadedReturn<T, U> = Extract<
T extends {
(...args: infer A1): infer R1;
(...args: infer A2): infer R2;
} ? U extends A1 ? [U, R1] : U extends A2 ? [U, R2] : never : never, [U, any]
>[1];
const gWrapper = () => {
const { foo } = getG();
return <T extends OverloadedParams<G["foo"]>>(...args: T): OverloadedReturn<G["foo"], T> => {
return foo(args[0], args[1]);
}
}
关键是获取重载参数类型(而非子类型)的父类型,并使用重载函数的定义将其与适当的 return 类型相关联。
我仍然不明白,为什么花了这么长时间才解决,是为什么
type OverloadedReturn<T, U> = T extends {
(...args: infer A1): infer R1;
(...args: infer A2): infer R2;
} ? U extends A1 ? R1 : U extends A2 ? R2 : never : never;
无效。