大多数时候我读到我们应该尽可能多地使用类型推断。当编写函数时,我知道我们必须输入参数,因为它们无法推断,但为什么我们必须输入返回值?TypeScript 正在处理这个问题。显式键入函数的返回值有什么好处?到目前为止,我只读到我应该这样做,但没有人说为什么。
jon*_*rpe 17
编译器可以推断您的代码的用途,但它不知道您的意图。举个简单的例子:
function thing(value: string) {
return value === "foo" ? 123 : "456";
}
Run Code Online (Sandbox Code Playgroud)
推断的类型是function thing(value: string): 123 | "456",并且与实现相匹配,但这在任何有意义的意义上都是正确的吗?例如,也许我打算总是返回 a number;如果我告诉编译器,它可以告诉我我没有:
Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.(2322)
Run Code Online (Sandbox Code Playgroud)
特别是当您使用复杂的包装器/通用类型时(例如,我在使用 RxJS 可观察量的角度上看到了很多与此相关的问题),这确实可以帮助您尽早获得关于您的假设的反馈。
我还经常从事测试驱动开发(TDD)方面的工作,其中在实现之前编写测试的价值之一是,它使您有机会在更改接口的成本接近于零的情况下讨论接口。使用经典的 RPS 示例:
function rps(left: string, right: string) {
return "right";
}
it("returns 'right' for 'rock' vs. 'paper'", () => {
expect(rps("rock", "paper")).to.equal("right");
});
Run Code Online (Sandbox Code Playgroud)
这将编译并通过,但这就是我们想要的吗?现在我们可以讨论选项:
我们接受推断的类型吗function rps(left: string, right: string): string?
更具体一些,例如
type Throw = "rock" | "paper" | "scissors";
type Outcome = "left" | "right" | "draw";
function rps(left: Throw, right: Throw): Outcome { ... }
Run Code Online (Sandbox Code Playgroud)
使用枚举代替?
我们可以讨论权衡,并根据我们当时所知道的情况选择最佳选择。显式返回类型作为我们所做决定的文档。
如果您对代码进行 linting,我建议您犯@typescript-eslint/explicit-function-return-type一个错误,其理由如下:
函数返回值的显式类型使任何调用代码都清楚返回的类型。这确保了返回值被分配给正确类型的变量;或者在没有返回值的情况下,调用代码不会尝试使用不应该使用的未定义值。
这是使用显式返回类型的一个很好的理由。根据TS 维基:
添加类型注释,尤其是返回类型,可以为编译器节省大量工作。在某种程度上,这是因为命名类型往往比匿名类型更紧凑(编译器可能推断出这一点),这减少了读取和写入声明文件(例如增量构建)所花费的时间。类型推断非常方便,因此无需普遍执行此操作 - 但是,如果您发现代码中速度较慢的部分,尝试一下可能会很有用。
因此,如果您的编译性能没有任何问题,我认为不需要指定返回类型
在这里您可以找到有关编译性能的另一个问题/答案。它还与 TypeScript Performance wiki相关
PS您可以使用显式返回类型来禁止使用返回值的一些额外属性。考虑这个例子:
const foo = (): { age: number } => {
const result = {
age: 42,
name: 'John'
}
return result
}
const result = foo()
result.age // ok
result.name //error
Run Code Online (Sandbox Code Playgroud)
您可能已经注意到,显式{age:number}返回类型是返回值类型的超类型。但它很弱,因为如果你想返回文字对象,它就不起作用,如下所示:
const foo = (): { age: number } => ({
age: 42,
name: 'John' // error
})
Run Code Online (Sandbox Code Playgroud)
所以我不建议使用这种技术,但它值得了解。
注释函数的返回类型的主要原因与使用 Typescript 的主要原因相同:因为您希望编译器检查您的代码并在您犯某些类型的错误时为您提供有用的错误消息。
如果您让 Typescript 推断函数的返回类型,那么它推断的任何内容都将是函数的返回类型,即使推断的类型不是您想要的类型。在这种情况下,如果您尝试返回错误类型的内容,编译器将使用该错误类型作为函数的返回类型,并且当您尝试调用该函数并期望返回正确类型的内容时,您将收到错误 - 或者更糟,您不会收到错误,但您的代码将在运行时失败或执行错误的操作。
另一方面,如果您知道想要的返回类型是什么,并且希望编译器检查您的函数是否确实返回该类型的内容,那么您应该使用类型注释。在这种情况下,如果您尝试返回错误类型的内容,那么您将在函数本身中收到错误,而错误实际上在此处。
| 归档时间: |
|
| 查看次数: |
8031 次 |
| 最近记录: |