【问题标题】:How to specify types for overloaded function with multiple return types?如何为具有多种返回类型的重载函数指定类型?
【发布时间】:2021-07-14 03:16:47
【问题描述】:

以下 TypeScript 代码将无法编译:

interface ZeroFunc {
    (value: string): string;
    (value: number): number;
}

const zero: ZeroFunc = (value: string | number) =>
    typeof value === 'string' ? '' : 0;

错误:

Type '(value: string | number) => "" | 0' is not assignable to type 'ZeroFunc'.
  Type 'string | number' is not assignable to type 'string'.
    Type 'number' is not assignable to type 'string'. ts(2322)

似乎在抱怨返回类型。

这个错误是有道理的,即使函数实现正确。

有没有办法正确指定这个函数的类型,使用any作为返回类型?

是否有可能正确实现ZeroFunc接口?

编辑:

以下是对问题的更好说明:

function zero(value: string): string;
function zero(value: number): number;
function zero(value: string | number): string | number {
    return typeof value === 'string' ? '' : 0;
}

type ZeroFunc = typeof zero;

const zero2: ZeroFunc = (value: string | number): string | number {
    return typeof value === 'string' ? '' : 0;
}

zero2 的声明与上面的错误相同。但很明显,它们是完全相同的函数签名。我真的只是复制粘贴它。

ZeroFunc 类型的定义甚至与我上面的接口完全相同。

【问题讨论】:

  • 只需添加第三个重载,它将接受并返回字符串和数字的联合
  • @captain-yossarian 这不起作用,在这种情况下,返回类型需要是 string & number。现在看来,这是不可能的。

标签: typescript overloading union-types


【解决方案1】:

ZeroFunc 接口有两个方法与最终赋值的右侧不匹配(一个接受字符串或数字并返回字符串或数字的函数)。

我想我会这样做:

interface ZeroFunc {
  (value: string | number): string | number;
}

const zero: ZeroFunc = (value: string | number) => typeof value === 'string' ? '' : 0;

但是我想知道为什么这个接口是必要的。你想强制执行什么?

更新

我试图强制如果参数是数字,那么返回类型将是数字。而对于字符串参数,返回类型是字符串。

我想知道是否可能如下:

type ZeroFunc<T> = (value: T) => T;

// OK
const zeroString: ZeroFunc<string> = (value: string) => '';
// OK
const zeroNumber: ZeroFunc<number> = (value: number) => 0;

// Bad case caught: 
//   Type '(value: number) => string' is not assignable to type 'ZeroFunc<number>'.
//     Type 'string' is not assignable to type 'number'
const zeroBad: ZeroFunc<number> = (value: number) => '';

// But this is also bad and is NOT caught
const zero: ZeroFunc<string | number> = (value: string | number) => 0;

但似乎不是 - 最后一种情况会编译,因为返回值与类型 string | number 匹配。

【讨论】:

  • 我试图强制如果参数是数字,那么返回类型将是数字。对于字符串参数,返回类型是字符串。数字参数永远不会产生字符串,反之亦然。
【解决方案2】:

除非这个提议得到实施,否则这似乎是一个错误:https://github.com/microsoft/TypeScript/issues/34319

拥有implements 功能基本上可以解决这个问题。

另见:https://github.com/microsoft/TypeScript/issues/37824

特别是来自this comment:

[...] 在 #6075 中,我们在重载和实现的返回类型之间添加了一个特殊的双变量检查。这是一种不合理的松懈,但它使人们能够更轻松地对这些案例进行建模。

对于检查函数与重载类型之间的可分配性的一般情况,我们没有添加此检查,因为不清楚意图是否相同。

换句话说,带有纯function 的示例实际上也不应该编译,但它是允许的,因为否则事情会太烦人。

对于函数分配,这是不允许的,因为它会更容易破坏事物,而且收益不会超过风险。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    相关资源
    最近更新 更多