【问题标题】:TypeScript: override a method return type that has overloadsTypeScript:覆盖具有重载的方法返回类型
【发布时间】:2021-01-27 07:15:46
【问题描述】:

我正在开发一个用于制作 Rx Observables 代理的开源库。

(为简单起见,我将使用Box<A> 而不是Observable<A>)

它接受一个Box<A> 并返回一个类型{ [P in keyof A]: Box<A[P]> }。

有一个细微差别:这种新类型的所有方法也应该返回该方法结果的Box,同时保留它的参数类型。所以:

Box<{ m(a:string):any }>
// becomes
{ m(a:string):Box<any> }

我面临的问题是,当我尝试代理具有重载方法的 A 时,我只是重新定义了一个单一的方法定义,而不是整个重载组。

简化问题:

type Proxy<O> = { [P in keyof O]: Wrap<O[P]> }

type Wrap<O> = O extends (...a: infer P) => infer R
  ? (...args: P) => Proxy<R>
  : Proxy<O>

class A {
  m(a: number): any;
  m(a: string): any;
  m(...a:any[]) {}
}

let p = {} as Proxy<A>;
// p.m resolves to a single override
// m(a: string): void;
p.m('1') // > returns Proxy<any>
p.m(1)   // > Error: 1 is not string

Try this snippet in TS playground

有可能吗?

请帮我打字。谢谢!

注意事项:

没有打字就一切正常!

您可以在此处查看库:rxjs-proxify(src/proxify.ts 中定义的类型)

【问题讨论】:

    标签: typescript types type-conversion


    【解决方案1】:

    映射重载函数存在问题。如果你只使用O extends (...a: infer P) =&gt; infer R,你实际上总是会得到最后一个重载。无法获取任意数量的重载的参数,但您可以使用here 概述的技术创建条件类型来获取最多一定数量的重载的重载参数

    type Proxy<O> = { [P in keyof O]: OverloadedWrap<O[P]> }
    
    type OverloadedWrap<T> =
        T extends
            { (...args: infer A1): infer R1; (...args: infer A2): infer R2; (...args: infer A3): infer R3; (...args: infer A4): infer R4 } ? 
            { (...args: A1): Proxy<R1>; (...args: A2): Proxy<R2>; (...args: A3): Proxy<R3>; (...args: A4): Proxy<R4>; }:
        T extends
            { (...args: infer A1): infer R1; (...args: infer A2): infer R2; (...args: infer A3): infer R3; } ? 
            { (...args: A1): Proxy<R1>; (...args: A2): Proxy<R2>; (...args: A3): Proxy<R3>; }:
        T extends
            { (...args: infer A1): infer R1; (...args: infer A2): infer R2; } ? 
            { (...args: A1): Proxy<R1>; (...args: A2): Proxy<R2>; }:
        T extends
            { (...args: infer A1): infer R1; } ? 
            { (...args: A1): Proxy<R1>; }:
        Proxy<T>
    
    type Wrap<O> = O extends (...a: infer P) => infer R
        ? (...args: P) => Proxy<R>
        : Proxy<O>
    
    class A {
        m(a: boolean): any;
        m(a: number): any;
        m(a: string): any;
        m(...a: any[]) { }
    }
    
    let p = {} as Proxy<A>;
    p.m('1') // > returns Proxy<any>
    p.m(1)   // > returns Proxy<any>
    p.m
    

    Playground Link

    【讨论】:

    • 啊!奇迹般有效!谢谢!虽然我现在从Box 上的重载方法中得到了一些奇怪的行为:它们有 n 个重载,尽管默认为 B.method(a: any) 而不是 B.method(a: number)。将尝试弄清楚这一点。再次,非常感谢,提香?
    • 好点,谢谢!我看到 tsconfig 中的 strictFunctionTypes 也会影响为代理函数推断类型的方式。使用 strictFunctionTypes: true 表现良好,但没有它 - 它会中断。不确定这将如何影响图书馆的最终用户。我可能会等 TS 5 ?Ty!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多