Skip to content

Instantly share code, notes, and snippets.

@millsp
Last active July 10, 2022 06:45
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save millsp/1eec03fbe64592c70efa4c80515f741f to your computer and use it in GitHub Desktop.
Save millsp/1eec03fbe64592c70efa4c80515f741f to your computer and use it in GitHub Desktop.
Dotted paths with ts-toolbelt
import {
A,
F,
B,
O,
I,
} from 'ts-toolbelt';
type OnlyUserKeys<O> =
O extends L.List
? keyof O & number
: O extends M.BuiltInObject
? never
: keyof O & (string | number)
type PathsDot<O, I extends I.Iteration = I.IterationOf<'0'>> =
9 extends I.Pos<I> ? never :
O extends object
? {[K in keyof O & OnlyUserKeys<O>]:
`${K}` | `${K}.${PathsDot<O[K], I.Next<I>>}`
}[keyof O & OnlyUserKeys<O>]
: never
type PathDot<O, P extends string, strict extends B.Boolean = 1> =
P extends `${infer K}.${infer Rest}`
? PathDot<O.At<O & {}, K, strict>, Rest, strict>
: O.At<O & {}, P, strict>;
type Obj = {
a: Obj[],
b: { c: Obj},
d: 40
e: 50
};
declare const object: Obj;
declare function get<O extends object, P extends string>(
obj: O, path: A.Cast<P, PathsDot<O>>
): PathDot<O, P>;
const test0 = get(object, 'a.45.b.c.a.100.a.45.e');
const test1 = get(object, 'a.45.b.c.a.100.a.45.x');
@mattbryson
Copy link

Hi, I've been trying to get this to work but having a few issues. I had to add the imports for L and M, but even then I get a few errors like:

Namespace '"file:///node_modules/ts-toolbelt/out/Misc/_api"' has no exported member 'BuiltInObject'.

and

Type 'string' does not satisfy the constraint 'number'. for line 16 <'0'>

see an example here

Any pointers much appreciated - I'm trying to get IntelliSense working for dot notation paths.

Cheers

Matt

@millsp
Copy link
Author

millsp commented Mar 26, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment