Create object property string path generator with typescript

Volodymyr Yepishev - Apr 13 '21 - - Dev Community

Create object property string path generator with typescript

Wow, that was a large noun cluster. Well, what is it anyway?

Now, using some libraries/frameworks you might sometimes need to generate a string that would represent a path to a property of some object, for example when you need to perform a get on Angular's FormGroup or have nested form field in React Hook Form.

You could create several monstrous constants, ie something akin to:

const nestedAddressField = 'user.contacts.address';
Enter fullscreen mode Exit fullscreen mode

Or maybe use template strings and enums, but there is a better way.

Typescript 4 bring along amazing stuff: Template Literal Types
. These are the solution.

Now, using this amazing feature we can create a type with infinite recursion and a helper function to generate all possible property paths an object has for us.

Check this out. First let us create a type that would basically be a colletion of all possible string paths in an object:

// For convenience
type Primitive = string | number | bigint | boolean | undefined | symbol;

// To infinity and beyond >:D
export type PropertyStringPath<T, Prefix=''> = {
    [K in keyof T]: T[K] extends Primitive | Array<any> 
    ? `${string & Prefix}${ string & K }` 
    : `${string & Prefix}${ string & K }` | PropertyStringPath <T[K], `${ string & Prefix }${ string & K }.`> ;
}[keyof T];
Enter fullscreen mode Exit fullscreen mode

Basically what it does is iterating over object's properties and returning each field as a string with a given prefix. Initially the prefix is empty string, which is nothing. If it encounters a primitive or an array, it returns a string with prefix, if it encounters an object, it then invokes itself recursively, but adds a dot to the prefix. Easy-peasy.

Now what's left to do is to create a simple factory that can generate us helper functions to provide hints:

export function propertyStringPathFactory<T, R=string>(): (path: PropertyStringPath<T>) => R {
    return (path: PropertyStringPath<T>) => (path as unknown as R);
}
Enter fullscreen mode Exit fullscreen mode

So now instead of walking on eggshells with strings we can use helper function that safeguards us from making mistakes.

Have fun ^_^

Oh, and by the way, there's an npm package with this utility 💪

Demo

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player