Typescript 扩展(映射)元组类型

Typescript 扩展(映射)元组类型,typescript,rxjs,Typescript,Rxjs,在泛型函数中使用元组类型时,如何“扩展”源类型 假设我们要创建一个rxjs映射运算符,它返回源可观察值和另一个映射值: 导出函数mapExtended(映射:(输入:[T])=>R):运算符函数; 导出函数mapExtended(映射:(输入:[T1,T2])=>R:OperatorFunction; 导出函数mapExtended(映射:(输入:[T1,T2,T3])=>R:OperatorFunction; 导出函数mapExtended(映射:(输入:任意)=>R):运算符函数{ 返回(s

在泛型函数中使用元组类型时,如何“扩展”源类型

假设我们要创建一个rxjs映射运算符,它返回源可观察值和另一个映射值:

导出函数mapExtended(映射:(输入:[T])=>R):运算符函数;
导出函数mapExtended(映射:(输入:[T1,T2])=>R:OperatorFunction;
导出函数mapExtended(映射:(输入:[T1,T2,T3])=>R:OperatorFunction;
导出函数mapExtended(映射:(输入:任意)=>R):运算符函数{
返回(source$:Observable)=>source$.pipe(
映射(输入=>{
常量映射结果=映射(输入);
返回[…输入,映射结果];
}),
);
}
这似乎是可行的,但过载没有被正确检测到。
测试
的返回类型为,
可观察
,而不是预期的
可观察

const test=combinelatetest(共(1)、共(2))。管道(
mapExtend(([s1,s2])=>s1+s2),
);
是否存在某种条件类型检查来说明
T
不能是元组类型


我尝试通过对元组的映射类型支持实现同样的功能,但没有效果,因为我似乎无法(或者我不知道如何)“扩展”映射类型:

类型MapExtended2Input={[P in keyof T]:T[P]};
函数mapExtended2(映射:(输入:MapExtended2Input)=>R):运算符函数{
返回(source$:Observable)=>source$.pipe(
映射(输入=>{
常量映射结果=映射(输入);
常量结果:[MapExtended2Input,R]=[input,mappingResult];
返回结果;
}),
);
}
const test2=组合测试(共(1),共(2))。管道(
mapExtended2([s1,s2])=>s1+s2),
);
这里,返回类型也是可观察的,这是预期的,但我不知道如何向映射的元组类型“添加”类型。交叉似乎不起作用,或者我做错了


编辑: 没有rxjs的理想功能示例如下:

假设我需要一个函数
myFunc
,它有两个泛型类型参数:

  • 一种元组类型T,元素数目可变
  • 另一种R型
函数的结果应该是一个元组类型,它包含元组类型T的所有元素,并附加类型R的参数

e、 g:

myFunc(x,y);//应该返回[T,R]
myFunc(x,y);//应该返回[T1,T2,R]
myFunc;//应该返回[T1、T2、T3、R]
// ...

我想你要求的是:给定一个元组类型
L
(用于“列表”)和另一个类型
T
,生成一个新的元组类型,在
L
的末尾附加
T
。如果要调用
l.push(t)
,则为结果类型的排序。您可以这样做:

type Push<L extends any[], T> =
  ((r: any, ...x: L) => void) extends ((...x: infer L2) => void) ?
  { [K in keyof L2]-?: K extends keyof L ? L[K] : T } : never
看起来不错。现在您可以像这样声明
mapExtended()

declare function mapExtended<T extends any[], R>(
  mapping: (input: T) => R
): OperatorFunction<T, Push<T, R>>;
声明函数mapExtended(
映射:(输入:T)=>R
):运算符函数;
请注意,
mapExtended()
的实现可能不会进行类型检查,因为编译器无法轻松验证某些内容是否属于泛型
t
R
OperatorFunction
类型。所以你可能会想用一个或一个


我无法验证此行为,因为我没有安装rxjs。如果您需要rxjs特定的帮助,我相信会有人对此更了解。不管怎样,希望这有帮助。祝你好运

我认为您要求的是:给定一个元组类型
L
(用于“列表”)和另一个类型
T
,生成一个新的元组类型,在
L
的末尾附加
T
。如果要调用
l.push(t)
,则为结果类型的排序。您可以这样做:

type Push<L extends any[], T> =
  ((r: any, ...x: L) => void) extends ((...x: infer L2) => void) ?
  { [K in keyof L2]-?: K extends keyof L ? L[K] : T } : never
看起来不错。现在您可以像这样声明
mapExtended()

declare function mapExtended<T extends any[], R>(
  mapping: (input: T) => R
): OperatorFunction<T, Push<T, R>>;
声明函数mapExtended(
映射:(输入:T)=>R
):运算符函数;
请注意,
mapExtended()
的实现可能不会进行类型检查,因为编译器无法轻松验证某些内容是否属于泛型
t
R
OperatorFunction
类型。所以你可能会想用一个或一个


我无法验证此行为,因为我没有安装rxjs。如果您需要rxjs特定的帮助,我相信会有人对此更了解。不管怎样,希望这有帮助。祝你好运

什么是rxjs,函数的
管道的
做什么?如果这个问题是关于一个特定的库,为什么它没有适当的标记/命名?@m93a:rxjs的用法与这个问题无关,但是我添加了一个完整的标记,谢谢。供您参考,rxjs是一个非常流行的库:代码太复杂了。尝试用不同的东西替换不必要的类型,如
OperatorFunction
Observable
,这样我们就可以在纯TypeScript中复制这些类型。rxjs是什么?
管道
函数的
功能是什么?如果这个问题是关于一个特定的库,为什么它没有适当的标记/命名?@m93a:rxjs的用法与这个问题无关,但是我添加了一个完整的标记,谢谢。供您参考,rxjs是一个非常流行的库:代码太复杂了。尝试用不同的东西替换不必要的类型,如
OperatorFunction
Observable
,这样我们就可以在纯TypeScript中复制它了。很好!我尝试使用rest元组,但没有找到正确的解决方案。实际上,该实现不进行类型检查。在试图弄清楚它的时候,我也没有考虑如何区分多个源观测值的元组类型和数组类型的单个观测值。虽然所需运算符函数的意图很清楚,但我可能需要重新设置