持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情
前言
在学习typescript的过程当中,有一个github库对其类型的学习特别有帮助,是一个有点类似于leetcode的刷题项目,能够在里面刷各种关于typescript类型的题目,在上一篇文章中,我们完成了中等的第十五题,今天来做中等的第十六题 191-medium-append-argument
下面这个是类型体操github仓库:
191-medium-append-argument
import type { Equal, Expect } from '@type-challenges/utils'
type Case1 = AppendArgument<(a: number, b: string) => number, boolean>
type Result1 = (a: number, b: string, x: boolean) => number
type Case2 = AppendArgument<() => void, undefined>
type Result2 = (x: undefined) => void
type cases = [
Expect<Equal<Case1, Result1>>,
Expect<Equal<Case2, Result2>>,
]
从README和测试用例中能够得出,我们需要实现一个工具函数 AppendArgument 能够为一个函数类型新增入参
实现 AppendArgument
在这之前我们知道,通过 ...arg 和 infer 相互配合能够用一个数组提取出函数的所有入参:
type APPENDARG1 = ((a: number, b: string) => number) extends (...arg:infer Rest)=>infer End ? Rest : never
// type APPENDARG1 = [a: number, b: string]
并且相反的,我们能够为 ...arg 提供一个数组类型,用于作为函数的入参
type APPENDARG2 = (...arg:[a:1,b:2,c:3]) => number
// type APPENDARG2 = (a: 1, b: 2, c: 3) => number
那么知道这些之后,这道题就变得很简单了,我们只需要用 infer 获取原有的参数然后用一个数组把旧参数和新参数组合到一起。
type AppendArgument<Fn, A> = Fn extends (...arg: infer Rest) => infer End
? (...arg: [...Rest, A]) => End
: Fn;
type Case1 = AppendArgument<(a: number, b: string) => number, boolean>;
// type Case1 = (arg_0: number, arg_1: string, arg_2: boolean) => number
这样测试用例就能够全部通过了
知识点
关于上述提到了部分的知识点:
Rest参数infer关键字
对于函数来说,灵活的运用 Rest 参数是非常重要的,通过灵活的运用 Rest 参数和 infer 关键字,我们就能够实现大部分的函数类型修改。
总结
今天我们做完了中等的第十六题,题目具体的关键还是在于如何灵活使用 Rest 参数来获取函数的入参以及设置函数的入参。