Reputation: 9673
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
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; } } } }
Upvotes: 3