typescript - 使用可选重载时的剩余参数

标签 typescript

当重载函数时,我有时会使用以下模式:

export function foo(a: string): void;
export function foo(b: number): void;
export function foo(a: string, b: number): void;
export function foo(...args: [string] | [number] | [string, number]): void {
    /* ... */
}

这使得很容易确定使用了哪个原型(prototype),例如如果 args.length === 2args 已知为 [string, number]。对于更复杂的类型(考虑一下如果您有两个接口(interface)而不是 stringnumber),这可以简化很多。

但是,使用可选参数时我无法使其工作:

export function foo(a?: string): void;
//              ~~~ error TS2394: This overload signature is not compatible with its implementation signature.
export function foo(...args: [] | [string]): void {
    return;
}

我知道我可以简单地添加另一个重载而不使用可选参数,但组合很快就会变得难以管理。

export function foo(): void;
export function foo(a: string): void;
export function foo(...args: [] | [string]): void {
    return;
}

更具体的例子是:

interface Foo {
  /* ... */
}

interface Bar {
  /* ... */
}

interface Baz {
  /* ... */
}

function awesomeFunction(foo?: Foo, bar?: Bar): void;
function awesomeFunction(baz: Baz, foo?: Foo, bar?: Bar): void;
function awesomeFunction(...args:
  | [Foo | undefined, Bar | undefined]
  | [Baz, Foo | undefined, Bar | undefined]
): void {
  /* ... */
}

因为我知道如果 args[0]Baz 我也会知道 args 中的其余元素。但是,它不能像上面所示的 foo 函数一样工作。

输入所有排列会变成很多变体,并将每个参数输入为 arg1?: Foo | Baz,arg2:Foo | Bar, arg3: Bar 意味着我必须对不可能的变体进行类型检查。

有办法解决这个问题吗?

最佳答案

本质上有一个 direct equivalence between function parameter lists and tuple types 。特别是optional function parameters就像 (x?: string) => void 对应于 optional tuple elements就像 [string?] (或者,当您使用 tuple element labels 时,[x?: string])。

这意味着你可以写你的 overload像这样的实现:

function foo(a?: string): void;
function foo(...args: [string?]): void {
}

function awesomeFunction(foo?: Foo, bar?: Bar): void;
function awesomeFunction(baz: Baz, foo?: Foo, bar?: Bar): void;
function awesomeFunction(...args: [Foo?, Bar?] | [Baz, Foo?, Bar?]): void {
}

事实上,如果所有调用签名的返回类型都相同,您甚至不需要重载:

function bar(...args: [a?: string]): void { }
// bar(a?: string | undefined): void

当你调用一个接受剩余元组并集的函数时,它看起来像一个重载函数:

function awesomeFunction(...args:
  [foo?: Foo, bar?: Bar] | [baz: Baz, foo?: Foo, bar?: Bar]
): void { }
// 1/2 awesomeFunction(foo?: Foo | undefined, bar?: Bar | undefined): void
// 2/2 awesomeFunction(baz: Baz, foo?: Foo | undefined, bar?: Bar | undefined): void

虽然可以说 [string?][string] | 之间存在关系。 [],当可选元组元素可用时,尝试强制编译器查看它可能没有意义。

Playground link to code

关于typescript - 使用可选重载时的剩余参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76189472/

相关文章:

angular - 在 Angular 2 中引用 TypeScript 类型

html - Typescript,单击按钮时防止 Bootstrap Dropdown 关闭

angular - 如何将子组件的更改通知父级?

typescript - 如何将 TypeScript 中的 Enum 转换为返回 keyof typeof Enum 的数组?

javascript - 导航回根 - 菜单切换按钮坏了

typescript - 如何使用 Jest 和 TypeScript 模拟第三方 nodejs 模块功能?

typescript - 升级到 TS 0.9 后我得到 TS5007 : Cannot resolve referenced file:, 我该如何解决这个问题?

javascript - 使用 Typescript 将一个对象文字映射到另一个对象文字

angular - 删除组件本身

typescript - 如何在 typescript 的异步/等待函数中获取 promise 的值(value)?