ts体操类型通关 (中等 )(下部分)

245 阅读2分钟

练习地址

1978・Percentage Parser 

知识点

  1. 判断是否为数字字符串
T extends `${number}`

image.png

另一种思路

image.png

2070・Drop Char 

image.png

2257・MinusOne

大佬的解答,这题难度应该不算中等

一般解法只能计算不超过1000的数字

type NewArrByLeng<N extends number, A extends any[] = []> = A['length'] extends N ? A : NewArrByLeng<N, [...A, 1]>
type MinusOne<T extends number, A extends any[] = NewArrByLeng<T>> = A extends [infer F, ...infer R] ? R['length'] : 0

2595・PickByType

type PickByType<T, U> = {
  [k in keyof T as T[k] extends U ? k : never]: T[k]
}

2688・StartsWith

type StartsWith<T extends string, U extends string> = T extends `${U}${infer R}` ? true : false

2693・EndsWith

type EndsWith<T extends string, U extends string> = T extends `${infer R}${U}` ? true : false

2757・PartialByKeys

知识点:

  1. 快速复制一个对象 Omit<Obj, never>
type CloneObj<T> = {
  [k in keyof T]: T[k]
}
type PartialByKeys<T, K extends any = keyof T> = CloneObj<{
  [k in keyof T as k extends K ? never : k]: T[k]
} & {
  [k in K as k extends keyof T ? k : never]?: k extends keyof T ? T[k] : never
}>

// 精简版
type PartialByKeys<T, K extends keyof any = string> = Omit<{ [k in K & keyof T]?: T[k] } & Omit<T, K>, never>;

2759・RequiredByKeys

type RequiredByKeys<T, K extends string | number | symbol = keyof T> = Omit<Omit<T, K> & Required<Pick<T, K extends keyof T ? K : never>>, never>

2793・Mutable 

type Mutable<T> = {
  -readonly[k in keyof T]: T[k]
}

2852・OmitByType


type OmitByType<T, U> = {
  [k in keyof T as T[k] extends U ? never : k]: T[k]
}

2946・ObjectEntries

知识点:

去除联合类型中的undefined type RemoveUndefined<T> = [T] extends [undefined] ? T: Exclude<T, undefined>;

type RemoveUndefined<T> = [T] extends [undefined] ? T: Exclude<T, undefined>;
type ObjectEntries<T, P extends keyof T = keyof T> = P extends any ? [P, RemoveUndefined<T[P]>] : never


// 另一种产生联合类型的方式
type ObjectEntries<T> = {
  [K in keyof T]-?: [K, RemoveUndefined<T[K]>];
}[keyof T]

3062・Shift

type Shift<T> = T extends [infer F, ...infer R] ? [...R] : T

3188・Tuple to Nested Object

type TupleToNestedObject<T, U> = T extends readonly [infer F, ...infer R] ? F extends string ? {
  [k in F]: R extends never ? U : TupleToNestedObject<R, U>
} : U : U
// 更加精简的写法。不需要判断F是否是string,而是直接&string
type TupleToNestedObject<T, U> = T extends readonly [infer F, ...infer R] ? {
  [k in F & string]: R extends never ? U : TupleToNestedObject<R, U>
} : U

3192・Reverse 

type Reverse<T, L extends any[] = []> = T extends [infer F, ...infer R] ? Reverse<R, [ F, ...L]> : L

3196・Flip Arguments 

type Reverse<T, L extends any[] = []> = T extends [infer F, ...infer R] ? Reverse<R, [ F, ...L]> : L

type FlipArguments<T> = T extends (...a: infer P) => infer R ? (...b: Reverse<P>) => R : never

3243・FlattenDepth

这种思路是递归的时候带上最终的值

type FlattenDepth<T extends any[], N extends number = 1, H extends any[] = [], V extends any[] = []> = 
  H['length'] extends N
  ? T extends any[] ? [...V, ...T] : [...V, T] 
  : T extends [infer F, ...infer R]
     ? FlattenDepth<R, N, H, [...V, ...(F extends any[] ? FlattenDepth<F, N, [...H, 1], []> : [F])]>
        : [...V]
        

这种思路是直接构造出最终的结构,FlattenDepth返回结果就是T的扁平化结构(推荐)

type FlattenDepth<T extends any[], N extends number = 1, H extends any[] = []> = T extends [infer F, ...infer R]
 ? H['length'] extends N  ? T  : F extends any[] 
   ? [...FlattenDepth<F, N, [...H, 1]>, ...FlattenDepth<R, N, H>]
     : [F, ...FlattenDepth<R, N, H>]
      : T

3326・BEM style string

知识点

  1. 泛型(T)如果是never,内部直接使用 T extends xx 会直接返回never
  2. 除了联合类型通过extends可以触发遍历逻辑外,字符串模板也可以(第二种实现)
type IsString<T> = [T] extends [never] ? false : T extends string ? true : false
type BEM<B extends string, E extends string[], M extends string[], A extends string = E[number],  C extends string = M[number]> = 
  IsString<A> extends true
   ? IsString<C> extends true
    ? `${B}__${A}--${C}`: `${B}__${A}`
     : IsString<C> extends true ? `${B}--${C}`
        : B 

type BEM<B extends string, E extends string[], M extends string[]> = E[number] extends never
  ? M[number] extends never
  ? B
  : `${B}--${M[number]}`
  : M[number] extends never
  ? `${B}__${E[number]}`
  : `${B}__${E[number]}--${M[number]}`

3376・InorderTraversal

在T外层套一层[],避免ts报错死循环

type InorderTraversal<T extends TreeNode | null> = [T] extends [TreeNode]  ?  [...InorderTraversal<T['left']>, T['val'], ...InorderTraversal<T['right']>] : []

4179・Flip

type Flip<T extends Record<string | number, string | any>> = {
  [k in keyof T as `${T[k]}`]: k
}

4182・斐波那契序列

type Fibonacci<T extends number, F extends any[] = [1], S extends any[] = [1], I extends any[] = [1]> = I['length'] extends T 
    ? F['length'] 
    : Fibonacci<T, [...S], [...F,...S], [...I, 1]>

4260・AllCombinations

参考答案

没做出来,参考答案做的很巧妙

4425・Greater Than 

type GreaterThan<T extends number, U extends number, V extends any[] = []> = V['length'] extends T ? false : V['length'] extends U ? true : GreaterThan<T, U, [...V, 1]>

4471・Zip

type Zip<T extends any[], P extends any[] = [], I extends any[] = [], R extends any[] = []> = 
T[I['length']] extends undefined ? R : 
  P[I['length']] extends undefined ? R 
   : Zip<T, P, [...I, 1], [...R, [T[I['length']], P[I['length']]]]>

简洁版

type Zip<T extends any[], S> = T extends [infer L, ...infer R] ? S extends [infer SL, ...infer SR] ? [[L, SL], ...Zip<R, SR>] : []: []

4484・IsTuple

type IsTuple<T> =[T] extends [never] 
    ? false : T extends readonly any[]
        ? number extends T['length'] ? false : true : false

4499・Chunk

type Chunk<T, N, R extends any[] = [], L extends any[] = []> = L['length'] extends N
    ?  Chunk<T, N, [...R, L]> :  T extends [infer F, ...infer P]
        ?  Chunk<P, N, R, [...L, F]>  : L['length'] extends 0 ? R : [...R, L]

优化版本:少一个参数

type Chunk<T extends any[],C extends number,S extends any[] = []> = 
  S['length'] extends C?
    [S,...Chunk<T,C>]
    : T extends [infer F,...infer R]?
        Chunk<R,C,[...S,F]>
      : S['length'] extends 0? []: [S]

4518・Fill

type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T['length'],
  R extends unknown[] = [],
  S extends boolean = false
> = T extends [infer F, ...infer L] 
  ? R['length'] extends End ?  Fill<L, N, Start, End, [...R, F], false> 
    : R['length'] extends Start ?  Fill<L, N, Start, End, [...R, N], true>
      : Fill<L, N, Start, End, [...R, S extends true ? N : F], S>  : R

4803・Trim Right 

type TrimRight<S extends string> = S extends `${infer Left}${' ' | '\n' | '\t'}` ?   TrimRight<Left> : S

5117・去除数组指定元素

type IsIncludes<T extends number | number[], V> = T extends number[] ? V extends T[number] ? true : false : T extends V ? true : false
type Without<T extends any[], U extends number | number[]> = T extends [infer F, ...infer R] ? IsIncludes<U, F> extends true  ? Without<R, U> : [F, ...Without<R, U>] : []

5140・Trunc 

type Trunc<T extends number | string> = `${T}` extends `${infer R}.${infer N}` ? R : `${T}`

5153・IndexOf

敲重点,如何判断两个值绝对相同

  1. type IsEqual<T, U> = (<V>() => V extends T ? 1 : 0) extends (<V>() => V extends U ? 1 : 0) ? true : false

通过构造两个函数来对比,否则的话类似any这种和其他类型都相等,由此我们可以写出如何判断是否是any类型

type IsAny<T> = (<V>() => V extends any ? 1 : 0) extends (<V>() => V extends T ? 1 : 0) ? true : false

type IndexOf<T extends unknown[], U extends unknown, Count extends 1[] = []> =
  T extends [infer First, ...infer Rest] ? (
    (<V>() => V extends First ? 1 : 0) extends
    (<V>() => V extends U ? 1 : 0) ? (
      Count['length']
    ) : IndexOf<Rest, U, [...Count, 1]>
  ) : -1

5310・Join

type Join<T extends string[], U extends string> = T extends [infer F extends string, ...infer R extends string[]] ? `${F}${R['length'] extends 0 ? '' : U}${Join<R, U>}` : ''

5317・LastIndexOf

type LastIndexOf<T extends any[], V, I extends any[] = [], A extends number = -1> =
 T extends [infer L, ...infer R] 
  ? (<U>() => U extends L ? 1 : 0) extends (<U>() => U extends V ? 1 : 0)
   ?  LastIndexOf<R, V, [...I, 1], I['length']>
   : LastIndexOf<R, V, [...I, 1], A>
    : A

5360・Unique

Equal上面已经实现过了

type IsIncludes<T extends any[], V> = T extends [infer F, ...infer R] ? Equal<F, V> extends true ? true : IsIncludes<R, V> : false
type Unique<T extends any[], E extends any[] = []> = T extends [infer F, ...infer R] ? IsIncludes<E, F> extends true ? Unique<R, E> : Unique<R, [...E, F]> : E

5821・MapTypes

type Helper<R, V> = R extends { mapFrom: V; mapTo: any } ? R['mapTo'] : never
type MapTypes<T, R extends Record<'mapFrom' | 'mapTo', unknown>> = {
  [k in keyof T]: Helper<R, T[k]> extends never ? T[k] : Helper<R, T[k]>
}

稍微换下思路,就可以避免多计算一次

type MapTypes<T, R extends Record<'mapFrom' | 'mapTo', unknown>> = {
  [P in keyof T]: T[P] extends R['mapFrom'] ? R extends { mapFrom: T[P] } ? R['mapTo'] : never : T[P]
}

8987・Subsequence

type ConstructTuple<L extends number, R extends unknown[] = []> = R['length'] extends L ? R : ConstructTuple<L, [...R, unknown]>

8640・Number Range

type NumberRange<L extends number, H extends number, R extends number[] = [], P extends any[] = []> = 
  P['length'] extends H ? R[number] | H 
    : NumberRange<L, H, P['length'] extends L ? [...R, L] : R['length'] extends 0 ? R : [...R, P['length']], [...P, 1]>

8767・Combination

参考链接

type Combination<T extends string[], All = T[number], Item = All>
  = Item extends infer Item extends string
    ? Item | `${Item} ${Combination<[], Exclude<All, Item>>}`
    : never

8987・Subsequence

type Subsequence<T> = T extends [infer One, ...infer Rest]
  ? [One] | [...Subsequence<Rest>] | [One, ...Subsequence<Rest>]
  : []