【问题标题】:Typescript generic function overload with rest types带有休息类型的打字稿泛型函数重载
【发布时间】:2023-03-21 22:35:01
【问题描述】:

有什么方法(特殊语法)可以将 rest 之类的参数应用于 TypeScript 中的模板?

如果问题不清楚,请查看以下示例和 cmets。

问题是 - 我可以在这里申请休息...Types:

function mixIt<A, B>   (a: A, b: B): A & B;
function mixIt<A, B, C>(a: A, b: B, c: C): A & B & C;

/* 
 * ??
 * If I would like to add D, E, F, etc, do I have to overwrite it like above?
 */

function mixIt<A, B, C>(...args: any[]): any{
    let mixin = <A & B & C> {};

    args.forEach( obj => {
        for(let key in obj) {
            if( ! mixin.hasOwnProperty(key) ) {
                (<any>mixin)[key] = obj[key];
            }
        }
    });

    return mixin;
}

仅供参考 - 错误检测符合预期:

class X {x: number = 7;}
class Y {y: string = 'ok';}
class Z {z: boolean = false;}

let x = new X;
let y = new Y;
let z = new Z;

let xy = mixIt(x, y);
let xyz = mixIt(x, y, z);

xyz.z; // Ok;
xy.z; // Error - as expected. VS Code editor also highlights it

【问题讨论】:

标签: typescript generics


【解决方案1】:

编辑 由于原始答案打字稿在 3.0 中添加了对剩余参数中的元组的支持。有了这个,我们可以在没有所有重载的情况下达到预期的结果:

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

function mixIt<T extends any[]>(...args: T): UnionToIntersection<T[number]>{ 
    let mixin: any =  {};

    args.forEach( obj => {
        for(let key in obj) {
            if( ! mixin.hasOwnProperty(key) ) {
                mixin[key] = obj[key];
            }
        }
    });

    return mixin;
}

原答案

目前没有办法有可变数量的类型参数,有一个proposal on this。

目前这样做的唯一方法是根据需要向函数添加尽可能多的签名,因此在您的情况下,这将是:

function mixIt<A, B>   (a: A, b: B): A & B;
function mixIt<A, B, C>(a: A, b: B, c: C): A & B & C;
function mixIt<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;
function mixIt<A, B, C, D, E>(a: A, b: B, c: C, d: D, e: E): A & B & C & D & E;
function mixIt<A, B, C, D, E, F>(a: A, b: B, c: C, d: D, e: E, f: F): A & B & C & D & E &F ;
// Private signature
function mixIt(...args: any[]): any{ // no need for this to be generic
    let mixin: any =  {};

    args.forEach( obj => {
        for(let key in obj) {
            if( ! mixin.hasOwnProperty(key) ) {
                mixin[key] = obj[key];
            }
        }
    });

    return mixin;
}

【讨论】:

  • 您在现在通用的函数定义上留下了评论“不需要它是通用的”。但是,嘿,巧妙的把戏!
  • @Coderer 哎呀,删除它。看到它得到了投票,信息有点陈旧,想快速更新并忘记评论:)
  • 哇,UnionToIntersection 可以工作,但那里发生了一些神奇的事情……你能解释一下为什么以及它是如何工作的吗?乍一看U 被推断为I 所以U 应该等于I,但实际上并非如此。也没有U extends any检查一切都行不通,但U不能扩展any?
  • 我找到了一个更具描述性的答案:stackoverflow.com/a/50375286/5598194。理解的关键是“分布式条件类型”:typescriptlang.org/docs/handbook/release-notes/…。 U extends any 用于启用此语言功能并将推理分成几个,每个联合成员。由于I 位于逆变位置(即(k: U) =&gt; void)扩展(k: I) =&gt; void,然后I 扩展U),最终结果是所有候选类型的交集(这就是TS作品)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
  • 2017-12-14
  • 2020-07-08
  • 2021-10-04
  • 2023-02-22
  • 2021-11-26
相关资源
最近更新 更多