1 line
11 KiB
Text
1 line
11 KiB
Text
|
|
{"version":3,"file":"groupByProp.cjs","names":["purry","output: BoundedPartial<Record<AllPropValues<T, Prop>, T[number][]>>"],"sources":["../src/groupByProp.ts"],"sourcesContent":["import type {\n AllUnionFields,\n ConditionalKeys,\n EmptyObject,\n IsNever,\n Or,\n Simplify,\n} from \"type-fest\";\nimport type { ArrayRequiredPrefix } from \"./internal/types/ArrayRequiredPrefix\";\nimport type { BoundedPartial } from \"./internal/types/BoundedPartial\";\nimport type { FilteredArray } from \"./internal/types/FilteredArray\";\nimport type { IterableContainer } from \"./internal/types/IterableContainer\";\nimport type { TupleParts } from \"./internal/types/TupleParts\";\nimport { purry } from \"./purry\";\n\ntype GroupByProp<T extends IterableContainer, Prop extends GroupableProps<T>> =\n // Distribute unions.\n T extends unknown\n ? FixEmptyObject<EnsureValuesAreNonEmpty<GroupByPropRaw<T, Prop>>>\n : never;\n\n// For each possible value of the prop we filter the input tuple with the prop\n// assigned to the value, e.g. `{ type: \"cat\" }`\ntype GroupByPropRaw<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n> = {\n [Value in AllPropValues<T, Prop>]: FilteredArray<T, Record<Prop, Value>>;\n};\n\n// We can only group by props that only have values that could be used to key\n// an object (i.e. PropertyKey), or if they are undefined (which would filter\n// them out of the grouping).\ntype GroupableProps<T extends IterableContainer> = ConditionalKeys<\n ItemsSuperObject<T>,\n PropertyKey | undefined\n>;\n\n// The union of all possible values that the prop could have within the tuple.\ntype AllPropValues<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n> = Extract<ItemsSuperObject<T>[Prop], PropertyKey>;\n\n// Creates a singular object type that all items in the tuple would extend. This\n// provides us a way to check, for each prop, what are all values it would\n// have within the tuple. We use this to map which props are candidates for\n// grouping, and when a prop is selected, the full list of values that would\n// exist in the output. For example:\n// `{ a: number, b: \"cat\", c: string } | { b: \"dog\", c: Date }` is groupable\n// by 'a' and 'b', but not 'c', and when selecting by 'b', the output would\n// have a prop for \"cat\" and a prop for \"dog\".\ntype ItemsSuperObject<T extends IterableContainer> = AllUnionFields<\n // If the input tuple contains optional elements they would add `undefined` to\n // T[number] (and could technically show up in the array itself). Because\n // undefined breaks AllUnionFields we need to remove it from the union. This\n // is OK because we handle this in the implementation too.\n Exclude<T[number], undefined>\n>;\n\n// When the input array is empty the constructed result type would be `{}`\n// because our mapped type would never run; but this doesn't represent the\n// semantics of the return value for that case, because it effectively means\n// \"any object\" and not \"empty object\". This can happen in 2 situations:\n// A union of tuples where one of the tuples doesn't have any item with the\n// groupable prop, or when the groupable prop has a value of `undefined` for\n// all items. The former is extra problematic because it would add `| {}` to the\n// result type which effectively cancels out all other parts of the union.\ntype FixEmptyObject<T> = IsNever<keyof T> extends true ? EmptyObject : T;\n\n// Group by can never return an empty tuple but our filtered arrays might not\n// represent that. We need to reshape the tuples so that they always have at\n// least one item in them.\ntype EnsureValuesAreNonEmpty<T extends Record<PropertyKey, IterableContainer>> =\n Simplify<\n Omit<T, PossiblyEmptyArrayKeys<T>> &\n BoundedPartial<CoercedNonEmptyValues<Pick<T, PossiblyEmptyArrayKeys<T>>>>\n >;\n\n// Go over the keys the object and return those that their value can accept an\n// empty array.\ntype PossiblyEmptyArrayKeys<T extends Record<PropertyKey, IterableContainer>> =\n keyof T extends infer Key extends unknown\n ?
|