jiangshanmeta.github.io
jiangshanmeta.github.io copied to clipboard
type-challenges solution ( medium )
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]>