【发布时间】:2019-04-13 15:23:48
【问题描述】:
在泛型函数中使用元组类型时,如何“扩展”源类型?
假设我们要创建一个 rxjs 映射运算符,它返回源可观察值和另一个映射值:
export function mapExtended<T, R>(mapping: (input: [T]) => R): OperatorFunction<[T], [T, R]>;
export function mapExtended<T1, T2, R>(mapping: (input: [T1, T2]) => R): OperatorFunction<[T1, T2], [T1, T2, R]>;
export function mapExtended<T1, T2, T3, R>(mapping: (input: [T1, T2, T3]) => R): OperatorFunction<[T1, T2, T3], [T1, T2, T3, R]>;
export function mapExtended<R>(mapping: (input: any) => R): OperatorFunction<any, {}> {
return (source$: Observable<any>) => source$.pipe(
map(input => {
const mappingResult = mapping(input);
return [...input, mappingResult];
}),
);
}
这似乎可行,但未正确检测到过载。 test 的返回类型是 Observable<[[number, number], number]>,而不是预期的 Observable<[number, number, number]>:
const test = combineLatest(of(1), of(2)).pipe(
mapExtend(([s1, s2]) => s1 + s2),
);
是否有某种条件类型检查表明 T 不能是元组类型?
我尝试通过对元组的映射类型支持来完成同样的工作,但无济于事,因为我似乎无法(或者我不知道如何)“扩展”映射类型:
type MapExtended2Input<T> = { [P in keyof T]: T[P] };
function mapExtended2<T extends any[], R>(mapping: (input: MapExtended2Input<T>) => R): OperatorFunction<MapExtended2Input<T>, [MapExtended2Input<T>, R]> {
return (source$: Observable<MapExtended2Input<T>>) => source$.pipe(
map(input => {
const mappingResult = mapping(input);
const result: [MapExtended2Input<T>, R] = [input, mappingResult];
return result;
}),
);
}
const test2 = combineLatest(of(1), of(2)).pipe(
mapExtended2(([s1, s2]) => s1 + s2),
);
这里,返回类型也是Observable<[[number, number], number]>,这是意料之中的,但我不知道如何向映射的元组类型“添加”一个类型。相交似乎不起作用,或者我做错了。
编辑:
没有 rxjs 的所需功能的示例是:
假设我需要一个函数myFunc,它有 2 个泛型类型参数:
- 元组类型 T,具有可变数量的元素
- 另一种类型R
函数的结果应该是一个元组类型,包含元组类型 T 的所有元素,并附加 R 类型的参数。
例如:
myFunc<T, R>(x, y); // Should return [T, R]
myFunc<[T1, T2], R>(x, y); // Should return [T1, T2, R]
myFunc<[T1, T2, T3], R>; // Should return [T1, T2, T3, R]
// ...
【问题讨论】:
-
什么是rxjs,
of和pipe函数有什么作用?如果问题是关于特定库的,为什么没有适当地标记/命名它? -
@m93a: rxjs的用法和问题无关,不过我已经加了tag才完整,谢谢。供您参考,rxjs 是一个非常受欢迎的库:github.com/ReactiveX/rxjs
-
代码太复杂了。尝试用不同的东西替换像
OperatorFunction和Observable这样不必要的类型,这样我们就可以在纯 TypeScript 中复制它。
标签: typescript rxjs