Can';t使TypeScript泛型链工作

Can';t使TypeScript泛型链工作,typescript,typescript-generics,Typescript,Typescript Generics,我正在构建一个函数,它接受一个函数链,其中每个函数都转换前一个函数的结果。在给定的示例中,\u context应该相等{hello:'world',something:'else'}: function withWorld<Context extends {}>(context: Context) { return { ...context, hello: 'world' } } function withSomething<Context extends {}>(

我正在构建一个函数,它接受一个函数链,其中每个函数都转换前一个函数的结果。在给定的示例中,
\u context
应该相等
{hello:'world',something:'else'}

function withWorld<Context extends {}>(context: Context) {
  return { ...context, hello: 'world' }
}

function withSomething<Context extends {}>(context: Context) {
  return { ...context, something: 'else' }
}

test([withWorld, withSomething], (_context) => {})
下面是代码():

导出接口测试函数{
)

完全错误:

没有与此调用匹配的重载。
重载2中的第1个,'(条件:[(contextSolo:{})=>any],body:(contextBodySolo:any)=>any):any',给出了以下错误。
类型为“[(contextWithWorld:Context)=>any,(contextSomething:Context)=>any]”的参数不能分配给类型为“[(contextSolo:{})=>any]”的参数。
源有2个元素,但目标只允许1个。
重载2/2’(条件:[(contextA:{})=>unknown,(contextB:unknown)=>any],body:(contextBody:any)=>void):any',给出了以下错误。
Type'(contextSomething:Context)=>any'不可分配给Type'(contextB:unknown)=>any'。
参数“contextSomething”和“contextB”的类型不兼容。
类型“unknown”不可分配给类型“{}”。(2769)

这里有一个工作示例:

导出接口测试函数{
你可以找到其他可能对你感兴趣的例子

可变和不可变数组

const mutable1=[1,2]//number[]
常量mutable2=[{age:1},{name:'John'}]
type MutableLength=(typeof mutable2)['length']//number,我们不知道长度
//常数可变2:({
//年龄:人数;
//名称?:未定义;
// } | {
//名称:字符串;
//年龄?:未定义;
// })[]
//如您所见,如果您想对可变数组进行操作,TS将只从所有数组元素中生成一个union类型
常量不可变=[{age:1},{name:'John'}]作为常量
type ImmutableLength=(typeof immutable)['length']//长度是2,我们确切地知道数组的长度和所有元素的类型
//在这里,TS可以说您的数组有两个元素
更新,我希望最后:D

我的缺点是,我认为使用可变数组是不可能的,但我应该从不同的角度来看待这个问题

以下是工作解决方案:

type Fn=(…args:any[])=>any
//信用卡https://stackoverflow.com/questions/50374908/transform-union-type-to-intersection-type/50375286#50375286
类型UnionToIntersection=(U扩展任何?(k:U)=>void:never)扩展(
k:我推断
)=>无效
我
:从不;
导出接口测试函数{
(
条件:[(上下文:Ctx)=>A],
正文:(上下文:A)=>任何
):任何
(
条件:C,
正文:(上下文:UnionToIntersection)=>void
):任何
}
常量测试:TestFunction=()=>void 0
函数与世界(上下文:上下文){
返回{…上下文,世界:'hello'}
}
带有内容的函数(上下文:上下文){
返回{…上下文,某物:'else'}
}
带有Somethingelse的函数(上下文:上下文){
返回{…上下文,somethingElse:'smth-else'}
}
测试([有内容],(_上下文)=>void 0)
测试([withWorld],(_上下文)=>void 0)
测试([withWorld,withSomething,withSomethingElse],(_context)=>void 0)
元组是一个数组,每个索引具有单独的类型。因此长度是固定的

默认情况下,数组有一种类型,所有元素的类型相同,且长度不固定

元组必须手动强制。这很难看到,因为您的示例很复杂。这样做可以消除错误

改为

[withWorld, withSomething] as Tuple<typeof withWorld, typeof withSomething>
将此输入到Typescript中

let a=[1,'1']
将光标放在“a”上,它会显示

let a:(string|number)[]
而不是

let a:[string,number]

感谢您提供了一个选项,但这并不理想,因为如果某些函数将原始上下文替换为显式期望交叉点的类型,即:
return{world:'hello'},那么这种方法将不起作用
。我也很好奇如何将其扩展到3个或更多项目。我正在研究通用解决方案,这是我问自己的第一个问题;)谢谢!@SashaKoss我做了一个更新,为答案和示例向您询问了很多!TypeScript并没有提供一个更简单的解决方案,这让我感到惊讶。我希望我能找到一个API这并不要求用户以常量编写
。遗憾的是,解决方案没有正确地推断
\u上下文
。此外,必须显式强制会产生令人不快的API。的确,它不知道在不显式执行的情况下传递部分结果。有时,简单是最好的(可能总是如此)。
type Default=(withWorld|withSomething)[]
let a=[1,'1']
let a:(string|number)[]
let a:[string,number]