diff --git a/src/internals/helpers.ts b/src/internals/helpers.ts index 4c188988..3b36160b 100644 --- a/src/internals/helpers.ts +++ b/src/internals/helpers.ts @@ -138,4 +138,4 @@ export const getSelectionKeys = (pattern: any): string[] => { export const flatMap = ( xs: readonly a[], f: (v: a) => readonly b[] -): b[] => xs.reduce((acc, p) => acc.concat(f(p)), []); +): b[] => xs.reduce((acc, x) => acc.concat(f(x)), []); diff --git a/src/types/FindSelected.ts b/src/types/FindSelected.ts index ec813459..c2ac5b92 100644 --- a/src/types/FindSelected.ts +++ b/src/types/FindSelected.ts @@ -1,6 +1,12 @@ import type * as symbols from '../internals/symbols'; import type { AnyMatcher, Matcher, Pattern } from './Pattern'; -import type { Equal, Primitives, ValueOf, UnionToTuple } from './helpers'; +import type { + Equal, + Primitives, + ValueOf, + MergeUnion, + IsUnion, +} from './helpers'; type SelectionsRecord = Record; @@ -39,7 +45,7 @@ type FindSelectionUnionInArray< p, path extends any[] = [], output = never -> = i extends readonly (infer ii)[] +> = i extends readonly (infer iItem)[] ? p extends readonly [] ? output : p extends readonly [infer p1, ...infer pRest] @@ -51,10 +57,10 @@ type FindSelectionUnionInArray< output | FindSelectionUnion > : FindSelectionUnionInArray< - ii[], + iItem[], pRest, [...path, p['length']], - output | FindSelectionUnion + output | FindSelectionUnion > : p extends readonly [...infer pInit, infer p1] ? i extends readonly [...infer iInit, infer i1] @@ -65,10 +71,10 @@ type FindSelectionUnionInArray< output | FindSelectionUnion > : FindSelectionUnionInArray< - ii[], + iItem[], pInit, [...path, p['length']], - output | FindSelectionUnion + output | FindSelectionUnion > : // If P is a matcher, in this case, it's likely an array matcher p extends readonly [...(readonly (infer pRest & AnyMatcher)[])] @@ -76,7 +82,7 @@ type FindSelectionUnionInArray< : | output | FindSelectionUnion< - ii, + iItem, ValueOf

, [...path, Extract['length']] > @@ -100,8 +106,8 @@ export type FindSelectionUnion< select: sel extends Some ? { [kk in k]: [i, path] } | FindSelectionUnion : never; - array: i extends readonly (infer ii)[] - ? MapList> + array: i extends readonly (infer iItem)[] + ? MapList> : never; // FIXME: selection for map and set is supported at the value level map: never; @@ -141,42 +147,19 @@ export type MixedNamedAndAnonymousSelectError< export type SelectionToArgs = symbols.anonymousSelectKey extends keyof selections - ? // If the path is never, it means several anonymous patterns were `&` together - [selections[symbols.anonymousSelectKey][1]] extends [never] + ? // if there are several different paths for anonymous selections + // it means that P.select() has been used more than once. + IsUnion extends true ? SeveralAnonymousSelectError : keyof selections extends symbols.anonymousSelectKey ? selections[symbols.anonymousSelectKey][0] : MixedNamedAndAnonymousSelectError : { [k in keyof selections]: selections[k][0] }; -type ConcatSelections< - a extends SelectionsRecord, - b extends SelectionsRecord -> = { - // keys both on output and sel - [k in keyof a & keyof b]: [a[k][0] | b[k][0], a[k][1] & b[k][1]]; // the path has to be the same -} & { - // keys of a - [k in Exclude]: a[k]; -} & { - // keyso of b - [k in Exclude]: b[k]; -}; - -type ReduceToRecord< - selections extends any[], - output extends SelectionsRecord = {} -> = selections extends [infer sel, ...infer rest] - ? ReduceToRecord< - rest, - ConcatSelections, output> - > - : output; - export type Selections = FindSelectionUnion extends infer u ? [u] extends [never] ? i - : SelectionToArgs>> + : SelectionToArgs, SelectionsRecord>> : i; export type FindSelected = diff --git a/src/types/Pattern.ts b/src/types/Pattern.ts index 8e18d8fe..2f752204 100644 --- a/src/types/Pattern.ts +++ b/src/types/Pattern.ts @@ -157,7 +157,7 @@ type KnownPatternInternal< > = | primitives | PatternMatcher - | ([objs] extends [never] ? never : ObjectPattern>) + | ([objs] extends [never] ? never : ObjectPattern>>) | ([arrays] extends [never] ? never : ArrayPattern); type ObjectPattern = diff --git a/src/types/helpers.ts b/src/types/helpers.ts index f106820e..db41be64 100644 --- a/src/types/helpers.ts +++ b/src/types/helpers.ts @@ -226,7 +226,7 @@ type AllKeys = a extends any ? keyof a : never; // Merge unions of objects into a single object with unions of keys export type MergeUnion = | { - readonly [k in AllKeys]: a extends any + [k in AllKeys]: a extends any ? k extends keyof a ? a[k] : never