ts类型挑战【二十一】

154 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第23天,点击查看活动详情

题目三十四:remove-index-signature

// template.ts
type RemoveIndexSignature<T> = any
// test-cases.ts
import type { Equal, Expect } from '@type-challenges/utils'

type Foo = {
  [key: string]: any
  foo(): void
}

type Bar = {
  [key: number]: any
  bar(): void
}

type FooBar = {
  [key: symbol]: any
  foobar(): void
}

type Baz = {
  bar(): void
  baz: string
}

type cases = [
  Expect<Equal<RemoveIndexSignature<Foo>, { foo(): void }>>,
  Expect<Equal<RemoveIndexSignature<Bar>, { bar(): void }>>,
  Expect<Equal<RemoveIndexSignature<FooBar>, { foobar(): void }>>,
  Expect<Equal<RemoveIndexSignature<Baz>, { bar(): void; baz: string }>>,
]

实现“RemoveIndexSignature”,从对象类型中排除索引签名(类似:[key: string]: any)。

代码实现

  • 原代码
type RemoveIndexSignature<T> = any
  • 遍历传入的参数 T
type RemoveIndexSignature<T> = {
  [P in keyof T]: T[P]
}
  • 将键值 P 放入字符串中,判断是否和原先的内容相同(索引签名不是字符串)
type RemoveIndexSignature<T> = {
  [P in keyof T as P extends `${infer R}` ? R : never]: T[P]
}

题目三十五:percentage-parser

// template.ts
type PercentageParser<A extends string> = any
// test-cases.ts
import type { Equal, Expect } from '@type-challenges/utils'

type Case0 = ['', '', '']
type Case1 = ['+', '', '']
type Case2 = ['+', '1', '']
type Case3 = ['+', '100', '']
type Case4 = ['+', '100', '%']
type Case5 = ['', '100', '%']
type Case6 = ['-', '100', '%']
type Case7 = ['-', '100', '']
type Case8 = ['-', '1', '']
type Case9 = ['', '', '%']
type Case10 = ['', '1', '']
type Case11 = ['', '100', '']

type cases = [
  Expect<Equal<PercentageParser<''>, Case0>>,
  Expect<Equal<PercentageParser<'+'>, Case1>>,
  Expect<Equal<PercentageParser<'+1'>, Case2>>,
  Expect<Equal<PercentageParser<'+100'>, Case3>>,
  Expect<Equal<PercentageParser<'+100%'>, Case4>>,
  Expect<Equal<PercentageParser<'100%'>, Case5>>,
  Expect<Equal<PercentageParser<'-100%'>, Case6>>,
  Expect<Equal<PercentageParser<'-100'>, Case7>>,
  Expect<Equal<PercentageParser<'-1'>, Case8>>,
  Expect<Equal<PercentageParser<'%'>, Case9>>,
  Expect<Equal<PercentageParser<'1'>, Case10>>,
  Expect<Equal<PercentageParser<'100'>, Case11>>,
]

实现PercentageParser <T extends string>

根据/^(\+\\-)?(\d*)?(\%)?$/ 规律性匹配T并获得三个匹配。

结构应该是:[‘正负’、‘数字’、‘单位`]

如果未捕获,则默认为空字符串。

代码实现

  • 原代码
type PercentageParser<A extends string> = any
  • 设计函数 MatchSymbol,功能:从字符串中抽取符号
type MatchSymbol<T> = T extends `${infer F}${infer _}`
	? F extends '+' | '-'
		? F
		: ''
	: ''
  • 设计函数 MatchUnit,功能:从字符串中抽取单位
type MatchUnit<T> = T extends `${infer _}%` ? '%' : ''
  • 设计函数 MatchValue,功能:从字符串中抽取数值
type MatchValue<T> = T extends `${MatchSymbol<T>}${infer V}${MatchUnit<T>}` ? V : ''
  • 最后实现 PercentageParser
type PercentageParser<A extends string> = [MatchSymbol<A>, MatchValue<A>, MatchUnit<A>]

题目三十六:drop-char

// template.ts
type DropChar<S, C> = any
// test-cases
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  // @ts-expect-error
  Expect<Equal<DropChar<'butter fly!', ''>, 'butterfly!'>>,
  Expect<Equal<DropChar<'butter fly!', ' '>, 'butterfly!'>>,
  Expect<Equal<DropChar<'butter fly!', '!'>, 'butter fly'>>,
  Expect<Equal<DropChar<'    butter fly!        ', ' '>, 'butterfly!'>>,
  Expect<Equal<DropChar<' b u t t e r f l y ! ', ' '>, 'butterfly!'>>,
  Expect<Equal<DropChar<' b u t t e r f l y ! ', 'b'>, '  u t t e r f l y ! '>>,
  Expect<Equal<DropChar<' b u t t e r f l y ! ', 't'>, ' b u   e r f l y ! '>>,
]

从字符串中删除指定的字符。

代码实现

  • 原代码
type DropChar<S, C> = any
  • 传入的两个参数都是 string 类型
type DropChar<S extends string, C extends string> = any
  • S 进行拆分,看看能不能拆出包含 C 的字符串
type DropChar<S extends string, C extends string> = S extends `${infer First}${C}${infer Last}`
	? ...
	: ...
  • 如果没拆出来,说明 S 中已经没有 C 了,则直接返回
type DropChar<S extends string, C extends string> = S extends `${infer First}${C}${infer Last}`
	? ...
	: S
  • 如果拆出来了,则去除掉当前的字符串 C,递归调用 DropChar 方法
type DropChar<S extends string, C extends string> = S extends `${infer First}${C}${infer Last}`
	? DropChar<`${First}${Last}`, C>
	: S