【Typescript 系列】类型体操之中等篇题型(第十一节)解读

172 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

1. 引言

接着上一节中,接下来我们继续Ts中等篇的题型练习 https://github.com/type-challenges/type-challenges/blob/main/README.zh-CN.md 提供的TypeScript 类型体操姿势合集题型,目的是为了让大家更好的了解TS的类型系统,编写自己的类型工具,或者单纯的享受挑战的乐趣!

2. 题型

  1. Percentage Parser:实现类型 PercentageParser。根据规则 /^(+|-)?(\d*)?(%)?$/ 匹配类型 T。匹配的结果由三部分组成,分别是:[正负号, 数字, 单位],如果没有匹配,则默认是空字符串。
type PString1 = ''
type PString2 = '+85%'
type PString3 = '-85%'
type PString4 = '85%'
type PString5 = '85'

type R1 = PercentageParser<PString1> // expected ['', '', '']
type R2 = PercentageParser<PString2> // expected ["+", "85", "%"]
type R3 = PercentageParser<PString3> // expected ["-", "85", "%"]
type R4 = PercentageParser<PString4> // expected ["", "85", "%"]
type R5 = PercentageParser<PString5> // expected ["", "85", ""]

思路:    首先,这题解答需要用到infer 关键字以及extends 的约束功能推导出首尾的“+= 符号类型”以及“% 符号类型” 后,剩下的中间值在直接通过首尾 推导过滤后去除的部分就是我们需要回抛的中间值内容。 解答:


type ParserLeft<T extends string> = T extends `${infer M}${infer _}` ? M extends '+' | '-' ? M : '' : ''
type ParserRight<T extends string> = T extends `${infer _}%` ? `%` : '' 
type ParserCenter <T extends string> = T extends `${ParserLeft<T>}${infer Z}${ParserRight<T>}` ? Z : ''

type PercentageParser<A extends string> = [ParserLeft<A>, ParserCenter<A>, ParserRight<A>]

type Demo = PercentageParser<''> // type Demo = ["", "", ""]
type Demo2 = PercentageParser<'+'> // type Demo2 = ["+", "", ""]
type Demo3 = PercentageParser<'+1'> // type Demo3 = ["+", "1", ""]
type Demo4 = PercentageParser<'+100'> // type Demo4 = ["+", "100", ""]
type Demo5 = PercentageParser<'+100%'> // type Demo5 = ["+", "100", "%"]
type Demo6 = PercentageParser<'100%'> // type Demo6 = ["", "100", "%"]
type Demo7 = PercentageParser<'-100%'> // type Demo7 = ["-", "100", "%"]
type Demo8 = PercentageParser<'-100'> // type Demo8 = ["-", "100", ""]
type Demo9 = PercentageParser<'-1'> // type Demo9 = ["-", "1", ""]
type Demo10 = PercentageParser<'%'> // type Demo10 = ["", "", "%"]
type Demo11 = PercentageParser<'1'> // type Demo11 = ["", "1", ""]
type Demo12 = PercentageParser<'100'> // type Demo12 = ["", "100", ""]

2.Drop Char: 从字符串中剔除指定字符。

type Butterfly = DropChar<' b u t t e r f l y ! ', ' '> // 'butterfly!'

思路:    先使用infer 关键字拆分需要判断的字符串中各个字符;在使用extends 判断当前拆解的字符是否为我们需要过滤的字符;是这过滤接着执行递归操作处理下一个字符;反之,则保留并且继续执行递归操作处理下一个字符; 解答:

type DropChar<S extends string, C extends string> =  S extends `${infer M}${infer N}` ? 
  C extends M ? DropChar<N, C> : `${M}${DropChar<N, C>}` : ''
type Demo = DropChar<'butter fly!', ''> // type Demo = "butter fly!"
type Demo2 = DropChar<'butter fly!', ' '> // type Demo2 = "butterfly!"
type Demo3 = DropChar<'butter fly!', '!'> // type Demo3 = "butter fly"
type Demo4 = DropChar<'    butter fly!        ', ' '> // type Demo4 = "butterfly!"
type Demo5 = DropChar<' b u t t e r f l y ! ', ' '> // type Demo5 = "butterfly!"
type Demo6 = DropChar<' b u t t e r f l y ! ', 'b'> // type Demo6 = "  u t t e r f l y ! "
type Demo7 = DropChar<' b u t t e r f l y ! ', 't'> // type Demo7 = " b u   e r f l y ! "

3.MinusOne: 给定一个正整数作为类型的参数,要求返回的类型是该数字减 1。

type Zero = MinusOne<1> // 0
type FiftyFour = MinusOne<55> // 54

思路:    解答:

type MinusOne<T extends number, U extends any[] = []> = [...U, unknown]['length'] extends T ? U['length'] : MinusOne<T, [...U, unknown]>
// type MinusOne<T extends number, U extends any[] = []> = [...U, unknown]['length'] extends T ? true : false
type TextLength = []['length'] // type TextLength = 0
type TextBool<T> = []['length'] extends T ? true : false
type TextBoolDemo = TextBool<1> // type TextBoolDemo = false
type Demo = MinusOne<1> // type Demo = 0
type Demo2 = MinusOne<55> // type Demo2 = 54
type Demo3 = MinusOne<3> // type Demo3 = 2
type Demo4 = MinusOne<100> // type Demo4 = 99
type Demo5 = MinusOne<1101> // type Demo5 = any