typescript - 如何在 TypeScript 3+ 中正确输入通用元组剩余参数?

标签 typescript typescript3.0

在 TypeScript 3.0 之前,推断 N 元函数的类型涉及为已知泛型参数创建任意数量的函数重载,然后使用诸如 any 类型的剩余参数之类的东西编写函数实现。 TypeScript 3.0 改变了这一点,以便泛型类型可以扩展 any[],充当泛型元组。

这一更改很有意义,并且对我来说对于泛型参数本身来说效果很好,但我无法像 3.0 之前那样让类型流向返回类型。

这是一个例子:

const takeToPromise = <T>(obs$: Observable<T>): Promise<T> => 
    obs$.pipe(take(1)).toPromise();

export function resolveObservables(): Promise<any[]>;
export function resolveObservables<T1>(o1: Observable<T1>): Promise<[T1]>;
export function resolveObservables<T1, T2>(o1: Observable<T1>, o2: Observable<T2>): Promise<[T1, T2]>;
export function resolveObservables<T1, T2, T3>(o1: Observable<T1>, o2: Observable<T2>, o3: Observable<T3>): Promise<[T1, T2, T3]>;
// Etc on the overloads
export function resolveObservables(...obs: (Observable<any>)[]): Promise<any[]> {
   return Promise.all(obs.map(takeToPromise));
}

假设我只有 3 个重载(最多 T3)。如果我通过将数组传播到函数调用中来使用 resolveObservables,在 TS 3.0 中,我将收到错误:

Expected 0-3 arguments, but got 0 or more.

我可以通过固定的数量调用很好地使用它,但是一旦我尝试传播,我就会收到错误。任何使这项工作成功的尝试都以某种方式失败了。例如:

export function resolveObservables<T, U extends Observable<T>[]>(...obs: U): Promise<T[]>;

将无法捕获任何类型(类型为 {})。

是否有某种方法可以修改这些类型,以便我可以在不失去使用扩展参数的能力的情况下让类型流动?在我使用展开的情况下,我并不真正关心类型,如果我这样做,我认为我可以只使用元组类型。但根据我到目前为止所尝试的,我可以使用扩展但丢失类型,或者有类型但不能使用扩展。

我在这里缺少什么?

最佳答案

我们可以让它在 3.0 上大部分工作,但要获得完整的元组映射支持,我们需要等待 3.1。

首先你不需要额外的T参数,只需使用 U extends Observable<any>[] 的约束这将推断 U 的正确元组类型。

为了提取结果元组类型,我们可以使用映射类型和条件类型从可观察对象中提取结果类型。这部分几乎可以在 3.0 中使用。在 3.0 中,映射类型将破坏数组类型,以便只有索引操作对结果类型仍然有效,所有方法都将是 never 类型。 3.1 将使元组和数组上的映射类型更加符合预期(请阅读 PR 了解详细信息)。

export function resolveObservables
    <U extends Observable<any>[]>(...obs: U): Promise<ExtractObservableTypes<U>> {
    return null as any;
}


type ExtractObservableTypes<T> = {
    [P in keyof T] : T[P] extends Observable<infer U> ? U : never
}
let o!: Observable<number>
let o2!: Observable<string>


resolveObservables(o, o2).then(r => {
    r[0].toExponential // r[0] is number
    r[1].substring // r[1] is string
})

Playground link

关于typescript - 如何在 TypeScript 3+ 中正确输入通用元组剩余参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51714415/

相关文章:

javascript - 如何根据 Angular 选择值隐藏输入字段?

angular - 如何将动态添加的自定义组件注册为表单组中的表单控件

typescript - TS1238 : Unable to resolve signature of class decorator when called as an expression

reactjs - 在 TypeScript 项目之间共享代码(使用 React)?

typescript - 强制对象至少有一个键( Object.keys(o).length > 0 )

typescript - 如何 "import"TypeScript 定义文件中的命名空间

angular - 在 Angular 中单击时显示/隐藏 <ul>

angularjs - json 文件的严格数据类型

tsc - TS2538 : Type 'unique symbol' cannot be used as an index type

angular8 - @angular/material 自动完成的性能问题