yunliuyan / type-challenges

typescript-challenges
0 stars 2 forks source link

00002-medium-return-type #1

Open yunliuyan opened 11 months ago

yunliuyan commented 11 months ago

获取函数返回类型 中等 #infer #built-in

接受挑战    English 日本語 한국어

不使用 ReturnType 实现 TypeScript 的 ReturnType<T> 泛型。

例如:

const fn = (v: boolean) => {
  if (v)
    return 1
  else
    return 2
}

type a = MyReturnType<typeof fn> // 应推导出 "1 | 2"

测试案例:

import type { 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

返回首页 分享你的解答 查看解答
yunliuyan commented 11 months ago

思路

通过infer关键字进行类型推导。在 TypeScript 中,infer 是一种用于推导类型的关键字。它通常与条件类型一起使用,用于从条件类型中推导出一个新的类型。

infer 的语法如下:

type MyType<T> = T extends SomeType<infer U> ? U : never;

其中,infer U 表示从 T 中推导出一个新的类型 U,SomeType 是一个条件类型,用于根据类型条件选择不同的类型。如果 T 可以赋值给 SomeType,则返回类型 U,否则返回类型 never。

使用 infer 可以在条件类型中推导出一个新的类型,然后将该类型用于其他类型定义中。例如,可以使用 infer 推导出一个函数类型的参数类型或返回值类型,然后将该类型用于其他函数类型的定义中。

在 TypeScript 中,infer 是一种非常强大的类型推导工具,可以用于处理复杂的类型转换和类型推导问题。

代码实现

type MyReturnType<T extends (params: any) => any> = T extends (params: any) => infer U ? U : never
wudu8 commented 11 months ago
type MyReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer U ? U : never

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

type ReturnTypeTest1 = MyReturnType<() => string>; // type ReturnTypeTest1 = string
type ReturnTypeTest2 = MyReturnType<() => 123>; // type ReturnTypeTest2 = string
type ReturnTypeTest3 = MyReturnType<() => ComplexObject>; // type ReturnTypeTest3 = { a: [12, 'foo']; bar: 'hello'; prev(): number; }
type ReturnTypeTest4 = MyReturnType<() => Promise<boolean>>; // type ReturnTypeTest4 = Promise<boolean>
type ReturnTypeTest5 = MyReturnType<() => 'foo'>; // type ReturnTypeTest5 = "foo"
type ReturnTypeTest6 = MyReturnType<typeof fn>; // type ReturnTypeTest6 = 1 | 2
type ReturnTypeTest7 = MyReturnType<typeof fn1>; // type ReturnTypeTest7 = 1 | 2
Janice-Fan commented 11 months ago

type MyReturnType<T extends (params: any) => any> = T extends (params: any) => infer U ? U : never

const fn = (v: boolean) => { if (v) return 1 else return 2 }

type a = MyReturnType // 应推导出 "1 | 2"

Naparte commented 11 months ago
// 不使用 ReturnType 实现 TypeScript 的 ReturnType<T> 泛型。

type MyReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

const fn = (v: boolean) => {
    if (v)
        return 1
    else
        return 2
}
type t = typeof fn;
type a = MyReturnType<typeof fn> // 应推导出 "1 | 2"

// type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;