jiangshanmeta.github.io icon indicating copy to clipboard operation
jiangshanmeta.github.io copied to clipboard

type-challenges solution ( medium )

Open jiangshanmeta opened this issue 4 years ago • 0 comments

type-challenges

原项目地址

2・Get Return Type

type MyReturnType<T extends (...arg:any)=>any> = T extends (...arg:any)=>infer U?U:never;

3・Omit

type MyOmit<T, K extends keyof T> = Pick<T,Exclude<keyof T,K>>

8・Readonly 2

type MyReadonly2<T, K extends keyof T = keyof T> = Readonly<Pick<T,K>> & Omit<T,K>

9・Deep Readonly

type DeepReadonly<T extends object> = {
  readonly [K in keyof T]:T[K] extends object? T[K] extends Function?T[K]: DeepReadonly<T[K]>:T[K]
}

10・Tuple to Union

type TupleToUnion<T extends readonly any[]> = T[number]

12・Chainable Options

type Chainable<T={}> = {
  option<K extends string,U>(key: K, value: U): Chainable<T & {[P in K]:U}>
  get(): T
}

15・Last of Array

type Last<T extends any[]> = T extends [...any,infer U]?U:never;

16・Pop

type Pop<T extends any[]> = T extends [...infer U,any]?U:never;

20・Promise.all

type UnwrapPromise<T> = T extends Promise<infer U>?U:T;
declare function PromiseAll<T extends any[]>(values: readonly [...T]): Promise<{
  [K in keyof T]:UnwrapPromise<T[K]>
}>

62・Type Lookup

type LookUp<U extends {type:string}, T extends U['type']> = U extends {type:T}?U:never;

106・Trim Left

type Space = ' ' | '\n' | '\t'
type TrimLeft<S extends string> = S extends `${Space}${infer T}`?TrimLeft<T>:S

108・Trim

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

type Trim<S extends string> = TrimRight<TrimLeft<S>>

110・Capitalize

type Capitalize<S extends string> = S extends `${infer F}${infer R}`?`${Uppercase<F>}${R}`:S

116・Replace

type Replace<S extends string, From extends string, To extends string> = From extends ''?S:S extends `${infer F}${From}${infer L}`?`${F}${To}${L}`:S;

119・ReplaceAll

type ReplaceAll<S extends string, From extends string, To extends string> = From extends ''?S:S extends `${infer F}${From}${infer L}`?`${F}${To}${ReplaceAll<L,From,To>}`:S

191・Append Argument

type AppendArgument<Fn extends (...args:any)=>any, A> = (...a:[...Parameters<Fn>,A])=>ReturnType<Fn>

296・Permutation

type isNever<T> = [T] extends [never]?true:false;
type Permutation<T extends string,R extends string[] = [], K = T > = isNever<T> extends true?
  R:
  K extends T? Permutation<Exclude<T,K>,[...R,K]>:R

298・Length of String

type LengthOfString<S extends string,L extends string[]=[]> = S extends `${infer A}${infer O}`?LengthOfString<O,[...L,A]>:L['length']

459・Flatten

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

527・Append to object

type AppendToObject<T,U extends string,V> = {
  [K in (keyof T) | U]:K extends keyof T?T[K]:V
}

529・Absolute

type Absolute<T extends number | string | bigint> = `${T}` extends `-${infer U}`?`${U}`:`${T}`

531・String to Union

type StringToUnion<T extends string> = T extends `${infer F}${infer O}`?F | StringToUnion<O>:never

599・Merge

type Merge<F, S> = {
  [K in ( (keyof F) | (keyof S))]:K extends keyof S?S[K]:(K extends keyof F?F[K]:never)
}

610・CamelCase

type CamelCase<S extends string> = S extends `${infer F}-${infer T}${infer R}`?
  T extends '-'?
    `${F}-${CamelCase<`${T}${R}`>}`
    :
    `${F}${T extends Uppercase<T>?`-${T}`:Uppercase<T>  }${CamelCase<R>}`:S;

612・KebabCase

type KebabCase<S extends string,P extends string = ''> = 
  S extends `${infer F}${infer O}`?
    F extends Lowercase<F>?
      KebabCase<O,`${P}${F}`>
      :P extends ''? KebabCase<O,Lowercase<F>>:KebabCase<O,`${P}-${Lowercase<F>}`>
  :P

645・Diff

type Diff<O,O1> = {
  [K in Exclude<keyof O,keyof O1> |  Exclude<keyof O1,keyof O>]:K extends keyof O?O[K]:K extends keyof O1?O1[K]:never
}

949・AnyOf

type falsy = '' | false | 0| [] | {[x:string]:never};
type AnyOf<T extends readonly any[]> = T[number] extends falsy?false:true

1042・IsNever

type IsNever<T> = [T] extends [never]?true:false

1097・IsUnion

type IsUnion<T,U = T> = T extends U ?
  [U] extends [T]?false:true
  :never

1130・ReplaceKeys

type ReplaceKeys<U, T extends string, Y > = {
  [K in keyof U]:K extends T? (K extends keyof Y?Y[K]:never) : U[K] 
}

1367・Remove Index Signature

// 索引类型特点 不是具体的字面量类型 而是 string number
// 利用never类型过滤
type OmitIndexSignature<T> = 
  string extends T ? 
  never :
  number extends T?
    never:T
// https://github.com/zhongsp/TypeScript/blob/dev/zh/release-notes/typescript-4.1.md#%E5%9C%A8%E6%98%A0%E5%B0%84%E7%B1%BB%E5%9E%8B%E4%B8%AD%E6%9B%B4%E6%94%B9%E6%98%A0%E5%B0%84%E7%9A%84%E9%94%AE 
// 在映射类型中更改映射的键
type RemoveIndexSignature<T> = {
  [K in keyof T as OmitIndexSignature<K>]:T[K]
}

1978・Percentage Parser

type ParseRest<T extends string> = T extends `${infer U}%`?[U,'%']:[T,'']
type PercentageParser<A extends string> = 
  A extends `${infer F}${infer R}`?
    F extends '+' | '-'?
      [F,...ParseRest<R>]
      :
      ['',...ParseRest<A>]
  :['','','']

2070・Drop Char

type DropChar<S extends string, C extends string> = S extends `${infer A}${C}${infer B}`?
  DropChar<`${A}${B}`,C>
  :S

2257・MinusOne

type Make10Array<T extends any[]> = [
  ...T,
  ...T,
  ...T,
  ...T,
  ...T,
  ...T,
  ...T,
  ...T,
  ...T,
  ...T,
]
type oneDigitNum = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
type Make1Array<T extends string,L extends any[] = []> = `${L['length']}` extends T? L:Make1Array<T,[1,...L]>
type MakeArray<T extends string,L extends any[] = []> = T extends `${infer F}${infer R}`? MakeArray< R,[
  ...Make10Array<L>,
  ...Make1Array<F>
]> : L

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

type MinusOne<T extends number> = Pop<MakeArray<`${T}`>>['length']

2595・PickByType

解法一 利用 Key Remapping in Mapped Types

type FilterKey<V,U,K> = V extends U?K:never;

type PickByType<T, U> = {
  [K in keyof T as FilterKey<T[K],U,K>]:T[K]
}

解法二:

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}${string}`?true:false

2693・EndsWith

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

2757・PartialByKeys

// 为什么需要这个Copy https://github.com/microsoft/TypeScript/blob/main/doc/spec-ARCHIVED.md#3.11.2
// Two types are considered identical when
// they are intersection types with identical sets of constituent types
// 一个是交叉类型的 一个不是交叉类型 他们不是identical 虽然可能是类型兼容互相assignable

type Copy<T> = {
  [K in keyof T]:T[K]
}
type PartialByKeys<T , K extends keyof any = keyof T> = Copy<Partial<Pick<T,Extract<keyof T, K>>> & Omit<T,K>>

2759・RequiredByKeys

type Copy<T> = {
  [K in keyof T]:T[K]
}
type RequiredByKeys<T , K extends keyof any = keyof T> = Copy<Required<Pick<T,Extract<keyof T,K>>> & Omit<T,Extract<keyof T,K>>>

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

type ObjectEntries<T,U = Required<T>> = {
  [K in keyof U]:[K,U[K]]
}[keyof U]

3062・Shift

type Shift<T extends any[]> = T extends [any,...infer U]?U:never 

3188・Tuple to Nested Object

type TupleToNestedObject<T, U> = T extends [infer F,...infer R]?
  {
    [K in F&string]:TupleToNestedObject<R,U>
  }
  :U

3192・Reverse

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

3196・Flip Arguments

type Reverse<T> = T extends [infer F,...infer M,infer L]?
  [L,...Reverse<M>,F]
  :T
type FlipArguments<T extends (...args:any)=>any > = T extends (...args:infer P)=>infer R? (...args:Reverse<P>)=>R : never

3243・FlattenDepth

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

  : T;

3326・BEM style string

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

3376・InorderTraversal 🤓

interface TreeNode {
  val: number;
  left: TreeNode | null;
  right: TreeNode | null;
}
type InorderTraversal<T extends TreeNode | null, U extends TreeNode = NonNullable<T>> = 
  T extends null?
    []
    :[...InorderTraversal<U['left']>,U['val'],...InorderTraversal<U['right']>]

4179・Flip

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

4182・Fibonacci Sequence

type Fibonacci<T extends number,C extends any[] = [1,1,1],A extends any[] = [1],B extends  any[] = [1]> = 
  T extends 1? 
    1:
    T extends 2?
    1:
      C['length'] extends T?
        [...A,...B]['length']
        :Fibonacci<T,[1,...C],B,[...A,...B]>

4260・AllCombinations

type Combination<
  S extends string,
  U extends string='',
  K = S
> = 
[S] extends [never]?
  U: 
  K extends S? 
    Combination<Exclude<S,K>,U | `${U}${K}`>
    :U

type String2Union<S extends string,R extends string = never> = S extends `${infer F}${infer L}`? String2Union<L,R | F>:R


type AllCombinations<S extends string> = Combination<String2Union<S>>

4425・Greater Than

type GreaterThan<T extends number, U extends number,TL extends number[] = [],UL extends number[] = []> = 
  T extends U ?
    false:
    UL['length'] extends U?
      true :
      TL['length'] extends T?
        false:
        GreaterThan<T,U,[0,...TL],[0,...UL]>

4471・Zip

type Zip<T extends any[],U extends any[]> = 
  T extends [infer TF,...infer TR]?
    U extends [infer UF,...infer UR]?
      [[TF,UF],...Zip<TR,UR>]
    :[]
  :[]

4484・IsTuple

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

4499・Chunk

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 GreaterThan<T extends number, U extends number,TL extends number[] = [],UL extends number[] = []> = 
  T extends U ?
    false:
    UL['length'] extends U?
      true :
      TL['length'] extends T?
        false:
        GreaterThan<T,U,[0,...TL],[0,...UL]>

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


type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T['length'],
> = GreaterThan<End,Start> extends true?
      FillNormal<T,N,Start,End>:T

4803・Trim Right

type Separator = ' ' | '\n' | '\t';

type TrimRight<S extends string> = S extends `${infer R}${Separator}`? TrimRight<R>:S;

5117・Without

type Includes<
  T extends any[],
  U
> = 
T extends [infer F,...infer R]? 
  F extends U? 
    true:Includes<R,U>
  :false

type WithoutMulti<
  T extends any[],
  U extends any[],
  R extends any[] = []
> = 
T extends [infer F,...infer L]?
  Includes<U,F> extends true? WithoutMulti<L,U,R>:WithoutMulti<L,U,[...R,F]>
  : R

type Without<T extends any[], U extends (number | number[] )> = U extends number[]? WithoutMulti<T,U>:WithoutMulti<T,[U]>

5140・Trunc

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

5153・IndexOf

type IndexOf<
  T, 
  U,
  L extends any[] = []
> = 
  T extends [infer F,...infer R]?
    U extends F? L['length']:IndexOf<R,U,[1,...L]>
  : -1

5310・Join

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

5317・LastIndexOf

type LastIndexOf<T extends any[], U> = T extends [...infer I,infer L]? L extends U?I['length']: LastIndexOf<I,U> : -1;

5360・Unique

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

5821・MapTypes

type MapTypes<T, R extends {mapFrom:any,mapTo:any},U extends {mapFrom:any,mapTo:any} = R> = {
  [K in keyof T]:U extends R? (T[K] extends R['mapFrom']?  (T[K] extends U['mapFrom']?U['mapTo']:never ) :T[K]   ):never
}

7258・ObjectKeyPaths

type GenNode<K extends string | number,IsRoot extends boolean> = IsRoot extends true? `${K}`: `.${K}` | (K extends number? `[${K}]` | `.[${K}]`:never)

type ObjectKeyPaths<
  T extends object,
  IsRoot extends boolean = true,
  K extends keyof T = keyof T
> = 
K extends string | number ?
  GenNode<K,IsRoot> | (T[K] extends object? `${GenNode<K,IsRoot>}${ObjectKeyPaths<T[K],false>}`:never)
  :never;

7544・Construct Tuple

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

jiangshanmeta avatar Sep 06 '21 15:09 jiangshanmeta