【问题标题】:Typescript: how to implement a callable type with a conditional return type?Typescript:如何实现具有条件返回类型的可调用类型?
【发布时间】:2019-01-27 15:42:48
【问题描述】:

接口Foo有条件类型作为返回类型时如何实现?

interface Foo {
    <A, B>(a: A, b: B): A extends B ? string : number
}

const foo: Foo = (a, b) => a === b ? 'str' : 123

编译器产生这个错误:

Type '"str" | 123' is not assignable to type 'A extends B ? string : number'. Type '"str"' is not assignable to type 'A extends B ? string : number'.

Playground

我已经看到this 的问题,但我不知道如何将其翻译为我的示例。另外,我想知道与解决方法相比,官方/正确的方法是什么。

UPD:我在提到的问题中解决了它,但 Unional 的回答确实帮助我理解了这个问题。我是这样解决的:

interface Foo {
    <A, B>(a: A, b: B): A extends B ? string : number
    <A, B>(a: A, b: B): string | number
}

【问题讨论】:

  • 发布一个答案,看看是否有帮助。如果您正在寻找实际的实现细节,我建议您将类型与实现一起定义。由于您的实现是虚拟代码,我无法帮助您找出问题所在。
  • @unional 嗨,非常感谢!我正在消化你的回答。即使我的实现是虚拟代码,它仍然与真实的基本相同,但简化了。

标签: typescript typescript-typings


【解决方案1】:

你的类型定义很好。

问题是您似乎过于依赖类型系统来指导您的开发。

由于您将类型定义和实现分开,编译器自然会以不同的方式看待它们。

在这种情况下,请随时将您的实现转换为 any

您看到的错误是因为类型推断为您的实现创建了类型 (a: any, b: any) =&gt; "str" | 123

因此编译器抱怨该类型不能满足您在Foo 中定义的类型。

没有额外的信息,这是编译器能做的最好的事情。

当然,当您实现代码时,编译器推断的类型很可能最终会满足您定义的类型。

但请记住,使用 TypeScript 的主要目的是提供信息以使用您编写的代码。使用类型来帮助实现是不错的,但这应该被视为一种奖励。

编译器并不完美,只有你真正知道你的意图。

这就是为什么有时如果您需要使用 any 来让事情顺利进行,请使用它(当然,始终要小心)。

这表明你的类型正在工作:

interface B { x: string }

interface A extends B { }

let a: A
let b: B
let c: string
const y = foo(a, b)  // y is string
const x = foo(c, b)  // x is number

记得编写单元测试来证明你的实现。 类型可以帮助你避免一类错误,但不是所有的错误。

更新:从 TypeScript 3.2 开始,我认为控制流分析(类型推断)不能推断条件类型。

【讨论】:

  • 一切似乎都说得通。谢谢!然而,我没有听从你关于使用any 的建议,我尽量避免这种做法。我所做的是添加一个以联合作为其返回类型的重载。
  • 添加更新:从 TypeScript 3.2 开始,我认为控制流分析(类型推断)不能推断条件类型。
  • 我也尽量避免any。确保您的工会超载对消费者有意义。这听起来像是一种泄漏类型(实现会影响规定的行为。应该反过来)。
  • 不,实际上它工作得很好。重要的部分是在原始调用签名(使用条件报告类型)之后添加带有联合的重载。因此,打字稿首先从函数调用的顶部重载中选择,然后选择第二个将其应用于实现。看到这个:stackoverflow.com/questions/50642020/…
  • 这就是我的意思。您使用条件类型来缩小返回类型,然后使用联合重载再次扩大它。您的消费者不需要重载签名。条件类型一充分描述了您的代码应该产生的所有结果。
猜你喜欢
  • 2021-05-03
  • 2021-01-03
  • 1970-01-01
  • 2020-05-09
  • 2018-11-11
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 2021-06-27
相关资源
最近更新 更多