Type Challenge

The answers of type challenge

Warm-up

Hello World

type HelloWorld = string;

Easy

Pick

type MyPick<T, K extends keyof T> = { [Key in K]: T[Key] };

Readonly

type MyReadonly<T> = { readonly [P in keyof T]: T[P] };

TupleToObject

type TupleToObject<T extends ReadonlyArray<any>> = {
  [P in T[number]]: P;
};

First Of Array

type First<T extends any[]> = T["length"] extends 0 ? never : T[0];

type First<T extends any[]> = T extends [infer F, ...infer Rest] ? F : never;

Length Of Tuple

type Length<T extends ReadonlyArray<any>> = T["length"];

Exclude

type MyExclude<T, U> = T extends U ? never : T;

Awaited

type MyAwaited<T> = T extends Promise<infer U> ? MyAwaited<U> : T;

If

type If<C extends boolean, T, F> = C extends true ? T : F;

Concat

type Concat<T extends ReadonlyArray<any>, U extends ReadonlyArray<any>> = [
  ...T,
  ...U
];

Includes

type isEqual<X, Y> = (<F>() => F extends X ? 1 : 2) extends <S>() => S extends Y
  ? 1
  : 2
  ? true
  : false;
type Includes<T extends readonly any[], U> = T extends [infer F, ...infer Rest]
  ? isEqual<F, U> extends true
    ? true
    : Includes<Rest, U>
  : false;

Push

type Push<T extends any[], U> = [...T, U];

Unshift

type Unshift<T extends unknown[], U> = [U, ...T];

Parameters

type MyParameters<T extends (...args: any[]) => any> = T extends (
  ...args: infer A
) => any
  ? A
  : never;

Medium

Get Return Type

type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

Omit

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

Readonly 2

type MyReadonly2<T, K = keyof T> = {
  readonly [Key in keyof T as Key extends K ? Key : never]: T[Key];
} & { [Key in keyof T as Key extends K ? never : Key]: T[Key] };

type MyReadonly2<T, K extends keyof T = keyof T> = {
  readonly [P in K]: T[P];
} & Omit<T, K>;

Deep Readonly

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

type PrimitiveType = number | string | boolean;
type AtomicObject = Function | Promise<any> | Date | RegExp;
type WeakReferences = WeakMap<any, any> | WeakSet<any>;
type Immutable<T> = T extends PrimitiveType
  ? T
  : T extends AtomicObject
  ? T
  : T extends ReadonlyMap<infer K, infer V>
  ? ReadonlyMap<Immutable<K>, Immutable<V>>
  : T extends ReadonlySet<infer V>
  ? ReadonlySet<Immutable<V>>
  : T extends WeakReferences
  ? T
  : T extends object
  ? { readonly [K in keyof T]: Immutable<T[K]> }
  : T;

TupleToUnion

type TupleToUnion<T extends any[]> = T extends [infer F, ...infer Rest]
  ? F | TupleToUnion<Rest>
  : never;

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

Chainable Options

type Chainable<Pre = {}> = {
  option<K extends string, V>(
    key: K extends keyof Pre ? never : K,
    value: V
  ): Chainable<Pre & { [key in K]: V }>;
  get(): Pre;
};

Last Of Array

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

type Last<T extends any[]> = T extends [infer F, ...infer Rest]
  ? T["length"] extends 1
    ? F
    : Last<Rest>
  : never;

Pop

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

Promise.All

type MyAwaited<T> = T extends Promise<infer U> ? MyAwaited<U> : T;
declare function PromiseAll<T extends readonly unknown[] | []>(
  values: T
): Promise<{ -readonly [P in keyof T]: MyAwaited<T[P]> }>;

LookUp

type LookUp<U, T> = U extends { type: T } ? U : never;

TrimLeft

type TrimLeft<S extends string> = S extends `${WhiteSpace}${infer Rest}`
  ? TrimLeft<Rest>
  : S;

Trim

type WhiteSpace = " " | "\t" | "\n";
type TrimLeft<S extends string> = S extends `${WhiteSpace}${infer Rest}`
  ? TrimLeft<Rest>
  : S;
type TrimRight<S extends string> = S extends `${infer Rest}${WhiteSpace}`
  ? TrimRight<Rest>
  : S;
type Trim<S extends string> = TrimLeft<TrimRight<S>>;

Capitalize

type MyCapitalize<S extends string> = S extends `${infer F}${infer Rest}`
  ? `${Uppercase<F>}${Rest}`
  : S;

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;

Replace All

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;

AppendArgument

type AppendArgument<Fn extends (...args: any[]) => any, I> = Fn extends (
  ...args: infer A
) => infer R
  ? (...args: [...A, I]) => R
  : never;

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

Permutation

type Permutation<T extends keyof any> = [T] extends [never]
  ? []
  : { [P in T]: [P, ...Permutation<Exclude<T, P>>] }[T];

LengthOfString

type LengthOfString<
  S extends string,
  A extends any[] = []
> = S extends `${infer L}${infer R}`
  ? LengthOfString<R, [...A, L]>
  : A["length"];

Flatten

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

AppendToObject

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

Absolute

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

StringToUnion

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

Merge

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

ConverToKebCase

type converToKebCase<S extends string> = S extends `${infer H}${infer Rest}`
  ? H extends Uncapitalize<H>
    ? `${H}${converToKebCase<Rest>}`
    : `-${Uncapitalize<H>}${converToKebCase<Rest>}`
  : "";
type KebabCase<S extends string> = converToKebCase<Uncapitalize<S>>;

Diff

type Diff<F, S> = {
  [K in keyof F | keyof S as K extends keyof F
    ? K extends keyof S
      ? never
      : K
    : K extends keyof S
    ? K
    : never]: K extends keyof F
    ? K extends keyof S
      ? never
      : F[K]
    : K extends keyof S
    ? S[K]
    : never;
};

AnyOf

type Empty = 0 | "" | false | [];
type isEmpty<T> = T extends Empty
  ? false
  : T extends {}
  ? keyof T extends never
    ? false
    : true
  : false;
type AnyOf<T extends readonly any[]> = T extends [infer F, ...infer Rest]
  ? isEmpty<F> extends true
    ? true
    : AnyOf<Rest>
  : false;

IsNever

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