dumbmatter
dumbmatter

Reputation: 9673

Converting a type containing string separated by periods into a nested object type

I have some string containing text separated by periods. There can be any number of periods, such as:

const stringX = "a.b";
const stringY = "a.b.c.d";

I want to use TypeScript to make some generic type StringToNestedObject that takes a string like that and outputs a type nested object type like:

type TypeX = StringToNestedObject<typeof stringX>;
// TypeX should be: { a: { b: string; } }

type TypeY = StringToNestedObject<typeof stringY>;
// TypeY should be: { a: { b: { c: { d: string; } } } }

The closest I can come up with for StringToNestedObject is:

type StringToNestedObject<S extends string> =
    S extends `${infer T}.${infer U}` ? {
        [T]: StringToNestedObject<U>
    } : {
        [S]: string
    };

but [T] and [S] don't actually work because:

A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.(1170)
'T' only refers to a type, but is being used as a value here.(2693)

Here is a TypeScript playground with the above non-working code.

(Why do I want to do this? IndexedDB key paths are string separated by periods which represent nested objects like this.)

Upvotes: 0

Views: 366

Answers (1)

dumbmatter
dumbmatter

Reputation: 9673

Okay maybe I should have played around a bit more before writing up a question :)

This works:

const stringX = "a.b";
const stringY = "a.b.c.d";

type StringToNestedObject<S extends string> =
    S extends `${infer T}.${infer U}` ? {[Key in T]: StringToNestedObject<U>} : {[Key in S]: string};

type TypeX = StringToNestedObject<typeof stringX>;
// TypeX should be: { a: { b: string; } }

type TypeY = StringToNestedObject<typeof stringY>;
// TypeY should be: { a: { b: { c: { d: string; } } } }

Playground

Upvotes: 3

Related Questions