一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情。
题目十二:return-type
// template.ts
type MyReturnType<T> = any
// test-cases.ts
import { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<string, MyReturnType<() => string>>>,
Expect<Equal<123, MyReturnType<() => 123>>>,
Expect<Equal<ComplexObject, MyReturnType<() => ComplexObject>>>,
Expect<Equal<Promise<boolean>, MyReturnType<() => Promise<boolean>>>>,
Expect<Equal<() => 'foo', MyReturnType<() => () => 'foo'>>>,
Expect<Equal<1 | 2, MyReturnType<typeof fn>>>,
Expect<Equal<1 | 2, MyReturnType<typeof fn1>>>,
]
type ComplexObject = {
a: [12, 'foo']
bar: 'hello'
prev(): number
}
const fn = (v: boolean) => v ? 1 : 2
const fn1 = (v: boolean, w: any) => v ? 1 : 2
这道题目要求我们实现内置的 ReturnType 类型,而不是直接使用它,可参考TypeScript官方文档。
官方介绍:构造一个由函数类型的返回类型组成的类型。
也就是获取函数的返回值类型。
- 示例1
type T0 = ReturnType<() => string>; // type T0 = string
很显然,函数返回值类型是 string,所以 T0 的值也是 string
- 示例2
type T1 = ReturnType<(s: string) => void>; // type T1 = void
- 示例3
type T2 = ReturnType<<T>() => T>; // type T2 = unknown
ts 中的 T(泛型),代指任意类型中的一个,所以这里返回值是 unknown
- 示例4
type T3 = ReturnType<<T extends U, U extends number[]>() => T>; // type T3 = number[]
这里定义了两个泛型:T 和 U,其中 U 是继承自 number[] 类型,T 则是继承 U 类型。所以 T 也是 number[] 类型
- 示例5
declare function f1(): { a: number; b: string };
type T4 = ReturnType<typeof f1>; // type T4 = { a: number; b: string; }
这里定义了一个函数 f1,该函数的返回值类型是一个对象:{ a: number, b: string }
所以这里 T4 的值也就是 f1 的返回值类型 { a: number, b: string }
- 示例6
type T5 = ReturnType<any>;
type T6 = ReturnType<never>;
type T7 = ReturnType<string>; // Error
type T8 = ReturnType<Function>; // Error
any 返回 any
never 返回 never
其他不满足条件的入参,直接报错
代码实现
- 原始代码
type MyReturnType<T> = any
- 入参应该是一个函数
type MyReturnType<T extends () => any> = any
- 入参的函数可能会有参数
type MyReturnType<T extends (...args: any[]) => any> = any
- 使用
infer定义函数的返回类型P
type MyReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer P
- 如果该约束成功,则返回
P否则返回any
type MyReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer P ? P : any
**