UNPKG

typescript-generic-types

Version:

A comprehensive collection of useful TypeScript generic types and utility types to enhance type-safety and developer experience. Includes array, promise, object manipulation, and advanced conditional types.

247 lines (197 loc) 7.33 kB
type ObjectId = string type Env = 'test' | 'development' | 'production' | 'preprod' | 'build' | 'ci' type MaybeArray<T> = T | T[] type MaybePromise<T> = T | Promise<T> type HasKeys<T> = keyof T extends never ? false : true type FunctionGeneric = (...params: any[]) => any type ObjectGeneric = { [k: string]: any } type ObjectWithNoFn = { [name: string]: NotFunction<any> } // eslint-disable-next-line @typescript-eslint/ban-types type NotFunction<T> = T extends Function ? never : T type AsType<T, Type> = T extends Type ? T : Type type AsString<T> = AsType<T, string> type Complete<T> = { [P in keyof Required<T>]: T[P]; } type CountryCodeIso = `${Letters}${Letters}` type TranslationObj = { [countryIsoCode in CountryCodeIso]?: string } type Override<T1, T2> = Omit<T1, keyof T2> & T2 type RecursivePartial<T> = { [P in keyof T]?: T[P] extends (infer U)[] ? RecursivePartial<U>[] : T[P] extends object ? RecursivePartial<T[P]> : T[P]; } type Letters = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' type SimpleNumbers = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 type ArrayOneOrMore<T> = { 0: T } & Array<T> type RecursiveObjValueType<T, Type> = { [K in keyof T]?: T[K] extends object ? Type | RecursiveObjValueType<T[K], Type> : Type; } type TypeObjectValues<Obj extends Record<string, any>, Type> = { [K in keyof Obj]: Type; } /** Return true | false whenever an object has a property of type U */ type HasPropertyOfType<Objectt extends Record<string, any>, ExpectedType> = { [K in keyof Objectt]: Objectt[K] extends ExpectedType ? true : never; }[keyof Objectt] extends never ? false : true // https://stackoverflow.com/questions/49580725/is-it-possible-to-restrict-typescript-object-to-contain-only-properties-defined type NoExtraProperties<T, U extends T = T> = U & MakeObjKeysAsNever<Exclude<keyof U, keyof T>> type MakeObjKeysAsNever<K extends keyof any> = { [P in K]: never } type RemoveTypeFromTuple<T, TypeToRemove> = T extends [] ? [] : T extends TypeToRemove ? [] : T extends [infer A, ...infer R] ? [ ...RemoveTypeFromTuple<A, TypeToRemove>, ...RemoveTypeFromTuple<R, TypeToRemove> ] : [T] type GetTypeKeyFromObject<ObjType, Type> = { [P in keyof ObjType]: ObjType[P] extends Type ? never : P; }[keyof ObjType] /** Remove object key/values that are of a certain type */ type RemoveTypeFromObj<ObjType, Type> = Pick< ObjType, GetTypeKeyFromObject<ObjType, Type> > /** Get keys where the key type (number, string, Symbol...) is of Type */ type GetObjectKeysThatAreOfType<ObjType, Type> = { [P in keyof ObjType]: P extends Type ? P : never }[keyof ObjType] /** Remove Symbol and number from Object type */ type ForceStringKeyObject<Obj extends Record<any, any>> = Pick< Obj, GetObjectKeysThatAreOfType<Obj, string> > /** Get all indices of an array as a type. Eg: 0 | 1 | 2... */ type Indices<T extends readonly any[]> = Exclude< Partial<T>['length'], T['length'] > /** Remove Readonly Modifier */ type Writeable<T> = { -readonly [P in keyof T]: T[P] } /** Remove Readonly Modifier Recursively */ type DeepWriteable<T> = { -readonly [P in keyof T]: DeepWriteable<T[P]> } /** used to type generic function without having to do (...params: any) => any */ type GenericFunction = (...params: any[]) => any /** used like IsObject<ReturnType> extends true ? .... */ type IsObject<T> = T extends Record<string, any> ? T extends GenericFunction ? false : T extends any[] | readonly any[] ? false : true : false type ReadonlyDeep<T> = { readonly [P in keyof T]: IsObject<T[P]> extends true ? ReadonlyDeep<T[P]> : T[P]; } /** Equivalent of { myPropA: string, otherProp?: never } | { myPropA?: never, otherProp: string }. This would be written Exclusive<{ myPropA: string }, { otherProp: string }> */ type Exclusive< A extends Record<string, any>, B extends Record<string, any>, C extends Record<string, any> = {}, D extends Record<string, any> = {}, E extends Record<string, any> = {} > = | ({ [P in Exclude<keyof A | keyof C | keyof D | keyof E, keyof B>]?: never; } & B) | ({ [P in Exclude<keyof B | keyof C | keyof D | keyof E, keyof A>]?: never; } & A) | ({ [P in Exclude<keyof B | keyof A | keyof D | keyof E, keyof C>]?: never; } & C) | ({ [P in Exclude<keyof B | keyof A | keyof C | keyof E, keyof D>]?: never; } & D) | ({ [P in Exclude<keyof B | keyof A | keyof C | keyof D, keyof E>]?: never; } & E) type WeekDays = 0 | 1 | 2 | 3 | 4 | 5 | 6 type StringAndUnion<T> = T | (string & {}) type ArrayKeys<Arr extends any[] | readonly any[]> = keyof Arr & number type PropsIntersection<T> = (T extends any ? (x: T) => void : never) extends (x: infer R) => void ? R : never /** Giving a list of object, this will return a type similar to O1 & O2 & O3... * * It works well when with this structure ```type ObjOfObj = Record<string, Record<string>>``` * * Giving that structure, if you want to extract ```ObjOfObj[keyof ObjOfObj]``` the type may be never because its impossible to match O1 | O2... */ type MergeMultipleObjects<Obj extends Record<string, any>> = PropsIntersection<Obj[keyof Obj]> /** Giving a list of required fields and subfields (dot notation) this type will return the object with the required fields added to type. @example ```ts type Obj = { a: string; aOptional?: string; b: { c?: string d?: string e: string } } type RequiredFields = { aOptional: true 'b.c': true } type Result = AddRequiredFieldsToObject<Obj, RequiredFields> // PARSED TYPE: type Obj = { a: string aOptional: string // this has became required because we specified it in RequiredFields b: { c: string // ALSO did this field d?: string // this one has kept being optional e: string // " " " " required } } ``` */ type AddRequiredFieldsToObject<Obj extends Record<string, any>, RequiredFields extends Record<string, boolean>> = RemoveTypeFromObj<Required<{ [K in keyof Obj]: K extends string // ? Obj[K] extends any[] | readonly any[] ? Obj[K] : ? K extends keyof RequiredFields ? (RequiredFields[K] extends true ? IsObject<Obj[K]> extends true ? AddRequiredFieldsToObject<Obj[K], { [P in keyof RequiredFields as P extends `${K}.${infer R}` ? R : never]: RequiredFields[P]; }> : Obj[K] : never) : never : never }>, never> & RemoveTypeFromObj<{ [K in keyof Obj]: K extends string // ? Obj[K] extends any[] | readonly any[] ? Obj[K] : ? K extends keyof RequiredFields ? never : IsObject<Obj[K]> extends true ? AddRequiredFieldsToObject<Obj[K], { [P in keyof RequiredFields as P extends `${K}.${infer R}` ? R : never]: RequiredFields[P]; }> : Obj[K] : never }, never> /** * Removes the first element from a tuple type. * * @example * ```ts * type Example1 = RemoveFirst<[boolean, number, string]>; // [number, string] * type Example2 = RemoveFirst<[boolean, string]>; // [string] * type Example3 = RemoveFirst<[boolean]>; // [] * type Example4 = RemoveFirst<[]>; // never * ``` */ type RemoveFirstElementFromTuple<T extends any[]> = T extends [any, ...infer Rest] ? Rest : never;