laclys / Front-End_practice

Daily practice
5 stars 0 forks source link

TS函数返回类型怎样根据传入参数值的不同而改变 #149

Open laclys opened 3 years ago

laclys commented 3 years ago

工作上遇到一个问题,是这样的

假如一个函数test(p)
type p = 't' | 'h'

当test('t')时 返回值类型为 string;

当test('p')时 返回值类型为 number;

这里给出两种解答

  1. 重载
    
    type p = 't' | 'h'
    function test(p: 't'): number

function test(p: 'h'): string

function test(p: 't' | 'h'): number | string { if (p == "t") { return 123 } else { return "123" } }

2. 引入泛型,进行类型推断

现阶段的TS,无法做到  `p === 't'`或者 `p extends 't' `来推断出就是`type p = 't' | 'h'`中的't'_(ts 的自动推断主要依赖 `typeof`、`instanceof`、对象类型的属性判断等)_
所以我们显式的声明返回值类型_(借助interface)_。 并且通过`mapping type`得到返回类型

```typescript
interface TestReturn  {
    t: number
    h: string
    [key: string]: unknown
}

// types util
function isKeys(key: unknown): key is keyof TestReturn {
    return key === 'a' || key === 'b'
}

function test<T extends keyof TestReturn>(p: T): TestReturn[Key]

// 重载了一下防止未知字段传入
function test(key: string): unknown {
    const store: Values = {
         t: 123
         h: '123'
    }

    if (isKeys(key)) {
        return store[key]
    }

    return store[key]
}

个人比较喜欢第二种方式