typescript 为什么要指定函数返回类型?

8yoxcaq7  于 2023-01-21  发布在  TypeScript
关注(0)|答案(3)|浏览(141)

大多数时候我读到我们应该尽可能多地使用类型推断。当写一个函数时,我理解我们必须键入参数,因为它们不能被推断出来,但是为什么我们必须键入返回值呢?TypeScript正在处理这个问题。显式键入函数的返回值有什么好处?到目前为止,我只读到我应该这样做,但是没有人说为什么。

hm2xizp9

hm2xizp91#

编译器可以推断你的代码 * 做什么 *,但它不知道你 * 想要什么 *。

function thing(value: string) {
    return value === "foo" ? 123 : "456";
}

推断出的类型是function thing(value: string): 123 | "456",它与实现匹配,但它有任何意义吗?例如,也许我打算总是返回number;如果我告诉编译器,它会告诉我我没有:

Type 'string | number' is not assignable to type 'number'.
  Type 'string' is not assignable to type 'number'.(2322)

特别是当您使用复杂的 Package 器/泛型类型时(例如,我在angular中看到了很多与此相关的问题,其中使用了RxJS可观察项),这确实有助于获得关于您假设的早期反馈。
我也在测试驱动开发(TDD)方面做了很多工作,在实现之前编写测试的价值之一是,它让您有机会在更改接口的成本接近于零的时候讨论接口。

function rps(left: string, right: string) {
  return "right";
}

it("returns 'right' for 'rock' vs. 'paper'", () => {
  expect(rps("rock", "paper")).to.equal("right");
});

这将编译并通过,但这是我们 * 想要 * 的吗?现在我们可以讨论选项:

  • 我们接受推断的类型function rps(left: string, right: string): string吗?
  • 更具体地说,例如
type Throw = "rock" | "paper" | "scissors";
type Outcome = "left" | "right" : "draw";
function rps(left: Throw, right: Throw): Outcome { ... }

我们可以讨论权衡,并根据当时的知识选择最佳选项,显式返回类型作为我们所做决定的 * 文档 *。
如果您正在编写代码,我建议将@typescript-eslint/explicit-function-return-type设置为一个错误,其基本原理如下:
函数返回值的显式类型使任何调用代码都清楚返回什么类型。这确保了返回值被赋给正确类型的变量;或者在没有返回值的情况下,调用代码不会尝试使用不应该使用的未定义值。

lawou6xi

lawou6xi2#

以下是使用显式返回类型的一个很好的理由。根据TS wiki:
添加类型注解,特别是返回类型,可以保存编译器的大量工作。部分原因是命名类型比匿名类型更紧凑(编译器可能会推断出),这减少了阅读声明文件所花费的时间类型推断非常方便,所以没有必要普遍地这样做--然而,如果您发现代码中有一个较慢的部分,那么这可能是一个非常有用的尝试。
因此,如果您在遵从性方面没有任何问题,我认为不需要指定返回类型
在这里你可以找到另一个关于编译性能的问题/答案。它也与TypeScript Performance wiki有关
另外,你可以使用显式返回类型来禁止使用返回值的一些额外属性。考虑这个例子:

const foo = (): { age: number } => {
    const result = {
        age: 42,
        name: 'John'
    }
    return result
}

const result = foo()
result.age // ok
result.name //error

正如你可能已经注意到的,explicit {age:number}返回类型是返回值类型的超类型,但是它很弱,因为如果你想返回literal object,它就不起作用了,比如:

const foo = (): { age: number } => ({
    age: 42,
    name: 'John' // error
})

所以我不能推荐使用这种技术,但是它值得了解。

xxb16uws

xxb16uws3#

注解函数返回类型的主要原因与使用Typescript的主要原因完全相同:因为您希望编译器检查您的代码,并在您犯了某些类型的错误时给予有用的错误消息。
如果你让Typescript来推断你的函数的返回类型,那么无论它推断出什么,都将是函数的返回类型,即使推断出的类型不是你想要的类型。在这种情况下,如果你试图返回错误类型的东西,编译器将使用错误的类型作为函数“的返回类型,那么当您试图调用该函数并期望得到正确类型的内容时,您将得到一个错误--或者更糟的是,您不会得到错误,但您的代码将在运行时失败或做错误的事情。
另一方面,如果你知道你想要的返回类型,并且你想让编译器检查你的函数确实返回了该类型的东西,那么你应该使用类型注解,在这种情况下,如果你试图返回错误类型的东西,那么你会在函数本身得到一个错误,错误实际上是在哪里。

相关问题