millsp / ts-toolbelt

👷 TypeScript's largest type utility library
https://millsp.github.io/ts-toolbelt/
Apache License 2.0
6.67k stars 149 forks source link

Object.Paths broken with TS 4.9 #322

Open bsssshhhhhhh opened 1 year ago

bsssshhhhhhh commented 1 year ago

🐞 Bug Report

Describe the bug

Object.Paths doesn't seem to be working right with 4.9. Not sure where the bug is

Reproduce the bug

https://www.typescriptlang.org/play?ts=4.9.0-dev.20221011#code/JYWwDg9gTgLgBAbzgeQEYCsCmBjeBfOAMyghDgHIYBnAWhgggBtVNGZyBuAKC5gE8wmOGACGMABZU4AXhQYcMAHQAFMZIA8Sca0YQAXHCowowAHYBzOHgB8HIA

paths is of type readonly Key[] in 4.9

Expected behavior

The same snippet running in 4.8

https://www.typescriptlang.org/play?ts=4.8.4&ssl=3&ssc=46&pln=3&pc=44#code/JYWwDg9gTgLgBAbzgeQEYCsCmBjeBfOAMyghDgHIYBnAWhgggBtVNGZyBuAKC5gE8wmOGACGMABZU4AXhQYcMAHQAFMZIA8Sca0YQAXHCowowAHYBzOHgB8HIA

Possible Solution

Screenshots

Additional context

bissolli commented 1 year ago

Same issue here, anyone has any idea how to sort that out? It seems the lib is abandoned =/

bsssshhhhhhh commented 1 year ago

I just wrote my own version to replace it. Probably going to be doing that for the rest of my ts-toolbelt usages too

Rechdan commented 1 year ago

I'm having that same issue here, TypeScript 4.8 works just fine!

akay64 commented 1 year ago

Same issue here, anyone has any idea how to sort that out? It seems the lib is abandoned =/

Damn, ran into the same issue on my end @bissolli :D very sad.

bissolli commented 1 year ago

Same issue here, anyone has any idea how to sort that out? It seems the lib is abandoned =/

Damn, ran into the same issue on my end @bissolli :D very sad.

As we were not using the lib extensively we ended up removing the lib as it seems to be abandoned! Hope you find a solution on your end man ;)

bsssshhhhhhh commented 1 year ago

This ObjectPaths type is the code I used to replace ts-toolbelt's Object.Paths post-TS 4.9. It's probably not perfect in terms of weird edge cases, but works for what I need from it. It handles unions, circular types, and array paths.

TS Playground Link

type DistributedKeyof<Target> = Target extends any ? keyof Target : never;

type DistributedAccess<Target, Key> =
  Target extends any
    ? Key extends keyof Target
      ? Target[Key]
      : undefined
    : never;

type Leaf =
  | Date
  | boolean
  | string
  | number
  | symbol
  | bigint;

type DepthCounter = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

type ObjectPaths<
  Target,
  Depth extends DepthCounter[number] = 10
> = Depth extends never
  ? never
  : Target extends never
    ? never
    : Target extends Leaf
      ? never
      : {
        [Key in string & DistributedKeyof<Target>]: [Key] | (
          NonNullable<DistributedAccess<Target, Key>> extends (infer ArrayItem)[]
          ? | [Key, number]
            | (ObjectPaths<ArrayItem, DepthCounter[Depth]> extends infer V extends any[] 
                ? [Key, number, ...V] 
                : never
              )
          : (
            ObjectPaths<NonNullable<DistributedAccess<Target, Key>>, DepthCounter[Depth]> extends infer V extends any[]
            ? [Key, ...V]
            : never
          )
        )
      }[string & DistributedKeyof<Target>];

// ----------

type SomeType = {
    name: string;
    nested: {
        value: number;
    }[]
}

type p = ObjectPaths<SomeType>;
//   ^?
akay64 commented 1 year ago

I actually found this code online somewhere, does the same thing...

export type NestedKeyPaths<ObjectType extends object> = {
    [Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object
        ? `${Key}.${NestedKeyPaths<ObjectType[Key]>}`
        : `${Key}`;
}[keyof ObjectType & (string | number)];
bsssshhhhhhh commented 1 year ago

👍 That code is similar to mine, but doesn't handle unions or circular types