Page with useful typescript snippets Flatten type: type FlattenType<T> = T extends object ? { [P in keyof T]: FlattenType<T[P]>; } : T; Recursively renaming a property in an object: type FilterKey<T, U> = { [K in keyof T]: K extends keyof U ? never : K; }[keyof T]; type RenameKeyRecursively<T, U, R> = T extends U ? { [K in FilterKey<T, U>]: RenameKeyRecursively<T[K], U, R>; } & R : T; type MyType = { quayCraneName: string; b?: string; c: { quayCraneName: string; test: number; }; }; type Filter = { quayCraneName: string; }; type ReplacedType = { cheName: string; }; type NewType = FlattenType<RenameKeyRecursively<MyType, Filter, ReplacedType>>; Remap undefined properties to be allowed optional: type OptionalProps<T extends object> = Partial<{ [K in keyof T as T[K] extends NonNullable<T[K]> ? never : K]: T[K] extends object ? UndefinedToOptional<T[K]> : T[K]; }>; type RequiredProps<T extends object> = { [K in keyof T as T[K] extends NonNullable<T[K]> ? K : never]: T[K] extends object ? UndefinedToOptional<T[K]> : T[K]; }; type UndefinedToOptional<T extends object> = T extends (infer A)[] ? A extends object ? OptionalProps<A>[] & RequiredProps<A>[] : A : OptionalProps<T> & RequiredProps<T>; Specification pattern Easily composable filters with specifications: export interface Specification<T> { (input: T): boolean; } export function all<T>( ...specifications: Specification<T>[] ): Specification<T> { return (input: T): boolean => specifications.every((spec) => spec(input)); } export function some<T>( ...specifications: Specification<T>[] ): Specification<T> { return (input: T): boolean => specifications.some((spec) => spec(input)); } export function inverse<T>(specification: Specification<T>): Specification<T> { return (input) => !specification(input); } // Usage: function isEqual(num: number): Specification<number> { return (numFromList: number) => { return num === numFromList; }; } function isOdd(): Specification<number> { return (numFromList: number) => { return numFromList % 2 !== 0; }; } console.log([1, 2, 3].filter(some(all(isOdd(), isEqual(1)), isEqual(3)))); // logs 1, 3