Repository: solidjs/solid
File: packages/solid/store/src/store.ts (TypeScript)

Code before:

export type ArrayFilterFn<T> = (item: DeepReadonly<T>, index: number) => boolean;

export type StoreSetter<T, U extends PropertyKey[] = []> =
  | ((
      prevState: DeepReadonly<T>,
      traversed: U
    ) => DeepReadonly<T> | Partial<DeepReadonly<T>> | void)
  | DeepReadonly<T>
  | Partial<DeepReadonly<T>>;

export type Part<T, K extends KeyOf<T> = KeyOf<T>> = [K] extends [never]
  ? never // return never if key is never, else it'll return readonly never[] as well
  : K | readonly K[] | (number extends K ? ArrayFilterFn<T[number]> | StorePathRange : never);

// shortcut to avoid writing `Exclude<T, NotWrappable>` too many times
type W<T> = Exclude<T, NotWrappable>;

// specially handle keyof to avoid errors with arrays and any
type KeyOf<T> = number extends keyof T
  ? 0 extends 1 & T // if it's any just return keyof T
    ? keyof T
    : [T] extends [never] // keyof never is PropertyKey which number extends; return never
    ? never
    : number // it's not any or never so it's an array or tuple; exclude the non-number properties
  : keyof T;

type Rest<T, U extends PropertyKey[]> = 0 extends 1 & T
  ? [...Part<any>[], StoreSetter<any>]
  : [StoreSetter<T, U>] | DistributeRest<W<T>, KeyOf<W<T>>, U>;
// need a second type to distribute `K`
type DistributeRest<T, K, U extends PropertyKey[]> = [T] extends [never]
  ? never
  : K extends KeyOf<T>
  ? [Part<T, K>, ...Rest<T[K], [K, ...U]>]
  : never;

export interface SetStoreFunction<T> {
  <
    K1 extends KeyOf<W<T>>,
    K2 extends KeyOf<W<W<T>[K1]>>,
    K3 extends KeyOf<W<W<W<T>[K1]>[K2]>>,
    K4 extends KeyOf<W<W<W<W<T>[K1]>[K2]>[K3]>>,
    K5 extends KeyOf<W<W<W<W<W<T>[K1]>[K2]>[K3]>[K4]>>,
    K6 extends KeyOf<W<W<W<W<W<W<T>[K1]>[K2]>[K3]>[K4]>[K5]>>,
    K7 extends KeyOf<W<W<W<W<W<W<W<T>[K1]>[K2]>[K3]>[K4]>[K5]>[K6]>>
  >(
    k1: Part<W<T>, K1>,
    k2: Part<W<W<T>[K1]>, K2>,
    k3: Part<W<W<W<T>[K1]>[K2]>, K3>,
    k4: Part<W<W<W<W<T>[K1]>[K2]>[K3]>, K4>,

Review comment (refactor):
This solves a lot of issues, as originally using `keyof T` would break with arrays, as it included other undesired array properties. By using a custom `KeyOf` instead, we can simplify most of the other types greatly. Not sure if this should be exported. 

Code after:

export type ArrayFilterFn<T> = (item: DeepReadonly<T>, index: number) => boolean;

export type StoreSetter<T, U extends PropertyKey[] = []> =
  | ((
      prevState: DeepReadonly<T>,
      traversed: U
    ) => DeepReadonly<T> | Partial<DeepReadonly<T>> | void)
  | DeepReadonly<T>
  | Partial<DeepReadonly<T>>;

export type Part<T, K extends KeyOf<T> = KeyOf<T>> = [K] extends [never]
  ? never // return never if key is never, else it'll return readonly never[] as well
  : K | readonly K[] | (number extends K ? ArrayFilterFn<T[number]> | StorePathRange : never);

// shortcut to avoid writing `Exclude<T, NotWrappable>` too many times
type W<T> = Exclude<T, NotWrappable>;

// specially handle keyof to avoid errors with arrays and any
type KeyOf<T> = number extends keyof T
  ? 0 extends 1 & T // if it's any just return keyof T
    ? keyof T
    : [T] extends [never] // keyof never is PropertyKey which number extends; return never
    ? never
    : number // it's not any or never so it's an array or tuple; exclude the non-number properties
  : keyof T;

type Rest<T, U extends PropertyKey[]> =
  | [StoreSetter<T, U>]
  | (0 extends 1 & T
      ? [...Part<any>[], StoreSetter<any, PropertyKey[]>]
      : DistributeRest<W<T>, KeyOf<W<T>>, U>);
// need a second type to distribute `K`
type DistributeRest<T, K, U extends PropertyKey[]> = [T] extends [never]
  ? never
  : K extends KeyOf<T>
  ? [Part<T, K>, ...Rest<T[K], [K, ...U]>]
  : never;

export interface SetStoreFunction<T> {
  <
    K1 extends KeyOf<W<T>>,
    K2 extends KeyOf<W<W<T>[K1]>>,
    K3 extends KeyOf<W<W<W<T>[K1]>[K2]>>,
    K4 extends KeyOf<W<W<W<W<T>[K1]>[K2]>[K3]>>,
    K5 extends KeyOf<W<W<W<W<W<T>[K1]>[K2]>[K3]>[K4]>>,
    K6 extends KeyOf<W<W<W<W<W<W<T>[K1]>[K2]>[K3]>[K4]>[K5]>>,
    K7 extends KeyOf<W<W<W<W<W<W<W<T>[K1]>[K2]>[K3]>[K4]>[K5]>[K6]>>
  >(
    k1: Part<W<T>, K1>,
    k2: Part<W<W<T>[K1]>, K2>,