【问题标题】:Implementing a function with conditional return type in Typescript [duplicate]在 Typescript 中实现具有条件返回类型的函数 [重复]
【发布时间】:2021-05-03 13:51:57
【问题描述】:

假设我想编写一个可以接受单个参数的函数,该参数可以是可空或不可空类型。如果参数不可为空,则返回类型也应不可为空。同样,如果参数是可为空的类型,则返回类型也应该是。

以下是我实现该功能的尝试:

type TransformKey = 'one' | 'two' | 'three'
function transform<T extends TransformKey | null>(key: T): T extends TransformKey ? string : string | null {
    if (key === null)
        return null as any
    else
        return key.toUpperCase() as any
}

函数签名似乎是正确的,因为它在调用站点上实现了所需的行为,例如:

const neverNullArg = 'two'
const neverNullResult: string = transform(neverNullArg)

const maybeNullArg: TransformKey | null = 'three'
const maybeNullResult: string | null = transform(maybeNullArg)

即返回类型确实由参数类型以正确的方式确定。

但是,我的问题在于函数实现。如果不将返回值转换为 any,则两个返回语句都会导致 TS2322 错误:Type 'null'/'string' is not assignable to type 'T extends TransformKey ? string : string | null'。所以我想知道如何在不破坏使用as any casts 或// @ts-ignore 的打字系统的情况下以满足签名的方式实现该功能。

【问题讨论】:

  • 什么版本的打字稿?
  • @smac89,第 4 版

标签: typescript typescript-generics


【解决方案1】:

您可以为您的函数创建overloads

type TransformKey = 'one' | 'two' | 'three'

function transform(key: TransformKey): string;
function transform(key: TransformKey | null): string | null;
function transform(key: any): string | null {
    if (key === null)
        return null;
    else
        return key.toUpperCase();
}

测试

const neverNullArg = 'two'
const neverNullResult: string = transform(neverNullArg)

const maybeNullArg: TransformKey | null = 'three'
const maybeNullResult: string | null = transform(maybeNullArg)

另见:Writing Good Overloads

【讨论】:

  • 不幸的是,这个答案不能解决我的问题,错误标记的重复问题中的答案也不能解决。主要问题是第二次测试 (maybeNull) 没有反映预期的类型。它相当于neverNull 测试。 maybeNull 的正确定义是 'three' as TransformKey | null。使用此类参数调用 transform 会导致 TS2345 错误。 alwaysNull 的第三次测试与我的问题无关。
  • @arslancharyev31 更新了我的答案。现在对你有用吗?
  • 太棒了,完美运行,谢谢。使用 any 键入实现参数并在重载声明中缩小该类型是一种我以前从未想过的有趣方法。
  • @arslancharyev31 大声笑我看到它正在完成here,所以我只是采用了他们的答案。也许该答案应该是标记为重复的答案。这也是我在答案中的链接中完成的方式,所以我想这确实是打字稿的重载方式
  • 您的答案将这两个概念结合在一起,形成了一个新的、独特的答案。这些问题都不是我的重复。我可能没有根据我的问题的具体情况提出问题。
猜你喜欢
  • 2021-01-03
  • 1970-01-01
  • 2020-05-09
  • 2018-11-11
  • 2019-04-09
  • 2021-06-27
相关资源
最近更新 更多