Typescript 对两个泛型组合的限制

Typescript 对两个泛型组合的限制,typescript,Typescript,在TypeScript中有没有一种方式可以表达“只要它们的组合满足类型X,就可以传入任意两个对象” 因此,如果我有以下功能: function myFunction(options: {x: number, y: string}){ } 然后,我有一个函数,它想用两个对象的组合调用这个函数: function callMyFunction<A,B>(a:A,b:B){ myFunction({...a,...b}) } 但如果我这样做,则不会编译,例如: callMy

在TypeScript中有没有一种方式可以表达“只要它们的组合满足类型X,就可以传入任意两个对象”

因此,如果我有以下功能:

function myFunction(options: {x: number, y: string}){
}

然后,我有一个函数,它想用两个对象的组合调用这个函数:

function callMyFunction<A,B>(a:A,b:B){
    myFunction({...a,...b})
} 
但如果我这样做,则不会编译,例如:

callMyFunction({x:1},{}) //y missing
callMyFunction({},{y:"hello"}) //x missing
callMyFunction({},{}) //x and y missing
我知道可以使用
extends
限制泛型类型。但是有没有办法限制两种泛型类型的组合呢?我想象这样的情况:

function callMyFunction<A,B, A&B extends {x:number,y:string}>(a:A,b:B){
    myFunction({...a,...b})
}
函数调用MyFunction(a:a,b:b){
myFunction({…a,…b})
}
在TypeScript中有没有一种方式可以表达“只要它们的组合满足类型X,就可以传入任意两个对象”

这是一个很棒的问题!答案是肯定的

这里有一个方法。该方法使用了令人兴奋的TypeScript和JavaScript特性的混合。它使用泛型、rest
参数、数组分解结构、条件类型、
never
类型和元组类型。它还通过使用
和Options一样未知的
技术告诉编译器“我们知道的比它知道的多”

type Options = { x: number; y: string };
function myFunction(options: Options) {}

function callMyFunction<A, B>(
  ...[a, b]: A & B extends Options ? [A, B] : never
) {
  const options = { ...a, ...b };
  myFunction((options as unknown) as Options);
}
…所有这些都不能通过类型检查

/**
 * Argument of type `'[{ x: number; }, {}]'` is not assignable
 * to parameter of type `'never'`.ts(2345)
 */
callMyFunction({ x: 1 }, {});

/**
 * Argument of type `'[{}, { y: string; }]'` is not assignable
 * to parameter of type `'never'`.ts(2345)
 */
callMyFunction({}, { y: "hello" });

/**
 * Argument of type `'[{}, {}]'` is not assignable
 * to parameter of type `'never'`.ts(2345)
 */
callMyFunction({}, {});

由此产生的错误消息可能需要改进。实际上,错误消息并没有告诉开发人员关于所需参数的更多信息。比我更了解打字脚本的人可以插话询问我们是否可以改进错误消息。

这是。。。真令人印象深刻但是错误信息确实会使这变得不现实。我很确定是否还有其他类似的观点。这并不是我想要在生产代码中实现的答案。它看起来既不透明又难以阅读。
callMyFunction({}, { x: 1, y: "hello" });
callMyFunction({ x: 1 }, { y: "hello" });
callMyFunction({ x: 1, y: "hello" }, {});
/**
 * Argument of type `'[{ x: number; }, {}]'` is not assignable
 * to parameter of type `'never'`.ts(2345)
 */
callMyFunction({ x: 1 }, {});

/**
 * Argument of type `'[{}, { y: string; }]'` is not assignable
 * to parameter of type `'never'`.ts(2345)
 */
callMyFunction({}, { y: "hello" });

/**
 * Argument of type `'[{}, {}]'` is not assignable
 * to parameter of type `'never'`.ts(2345)
 */
callMyFunction({}, {});