TypeScript:如何编写具有条件返回类型的函数

12 typescript

export type Name = { name: string }
export type Id = { id: number }
export type Value<T> = T extends string ? Name : Id

export function create<T extends string | number>(value: T): Value<T> {
    if (typeof value === "string") return { name: value }

    return { id: value }
}
Run Code Online (Sandbox Code Playgroud)

我正在玩TypeScript中的条件类型.我想用条件返回类型编写一个函数.如果函数传递一个字符串,则返回一个Name,否则返回一个Id.

我的返回语句中出现以下错误:

Type '{ name: T & string; }' is not assignable to type 'Value<T>'.
Run Code Online (Sandbox Code Playgroud)

我错过了什么?日Thnx!

编辑:直接来自Anders Hejlsberg谈话的例子来自Build 2018:https://youtu.be/hDACN-BGvI8?t = 224l

他甚至声称"我们不再需要编写函数重载......"

如果我将代码更改为声明,编译错误就会消失:

export type Name = { name: string }
export type Id = { id: number }

export type Value<T> = T extends string ? Name : Id

declare function create<T extends string | number>(value: T): Value<T>

const a = create("Bob")     // a : Name
const b = create(5)         // b : Id
Run Code Online (Sandbox Code Playgroud)

所以我们可以声明函数签名.我想我的问题就变成了,我们将如何实际实现这个功能?

Tit*_*mir 6

问题在于该函数内部T未知,因此您无法真正为分配一个值Value<T>。一种选择是使用类型断言。类型更安全的选择是使用单独的实现签名,这将使输入和输出类型更加宽松:

export function create<T extends string | number>(value: T): Value<T> // public signature
export function create(value: string | number): Name | Id { // more relaxed private implementation signature 
    if (typeof value === "string") return { name: value }

    return { id: value }
}
Run Code Online (Sandbox Code Playgroud)

  • @titan cernicova-dragomir 我很困惑为什么 `T` 在函数内部是未知的,即使我们消除了这种可能性。我很难理解这一点。顺便说一句,如何确保公众会收到第一个签名? (3认同)

mes*_*eeb 6

这是另一个效果很好的解决方案。

我比接受的答案更喜欢这个解决方案,因为您在编码时会得到正确的类型推导

在此处输入图片说明

你可以看到当悬停时,它正确地推断出类型。

这是屏幕截图中的代码:

export type Name = { name: string }
export type Id = { id: number }
export type Value<T extends string | number> = T extends string ? Name : Id

export function create<T extends string | number>(value: T): Value<T> {
    if (typeof value === 'string') return { name: value } as unknown as Value<T>

    return { id: value } as unknown as Value<T>
}
Run Code Online (Sandbox Code Playgroud)