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