type JoinDot = `${K}${"" extends K ? "" : "."}${P}`; type PathDot = T extends object ? { [K in keyof T]: K extends string ? JoinDot | PathDot> : never; }[keyof T] : Acc; type PathHead = T extends [infer head] ? head : // eslint-disable-next-line @typescript-eslint/no-unused-vars T extends [infer head, ...infer rest] ? head : ""; // eslint-disable-next-line @typescript-eslint/no-unused-vars type PathRest = T extends [infer head, ...infer rest] ? rest extends [] ? never : rest : never; type PathLast = T["length"] extends 1 ? true : false; type Recursive = PathHead extends keyof T ? Omit> & { [P in PathHead]-?: PathLast extends true ? NonNullable : Recursive, PathRest>; } : T; type Split = Str extends `${infer Head}.${infer Rest}` ? Split : Str extends `${infer Last}` ? [...Acc, Last] : never; type SelectiveNonNullable> = Recursive, Split

>; export const isDefined = (t: T): t is NonNullable => t !== null && t !== undefined; export const isUndefined = (t: T | null | undefined): t is null | undefined => !isDefined(t); export const isDefinedAndNotEmpty = (string: string | null | undefined): string is string => isDefined(string) && string.length > 0; export const filterDefined = (t: T[] | null | undefined): NonNullable[] => isUndefined(t) ? [] : (t.filter((item) => isDefined(item)) as NonNullable[]); export const filterHasAttributes = >( t: T[] | null | undefined, paths: readonly P[] ): SelectiveNonNullable[] => isDefined(t) ? (t.filter((item) => hasAttributes(item, paths)) as unknown as SelectiveNonNullable< T, (typeof paths)[number] >[]) : []; const hasAttributes = (item: T, paths: readonly PathDot[]): boolean => isDefined(item) && paths.every((path) => hasAttribute(item, path)); const hasAttribute = (item: T, path: string): boolean => { if (isDefined(item)) { const [head, ...rest] = path.split("."); if (isDefined(head) && Object.keys(item).includes(head)) { const attribute = head as keyof T; if (isDefined(item[attribute])) { if (rest.length > 0) { return hasAttribute(item[attribute], rest.join(".")); } return true; } } } return false; };