Transforming a data structure with strings delimited by periods into a hierarchical object format

I have a string with text separated by periods. It can contain any number of periods, for example:

const sampleString1 = "a.b";
const sampleString2 = "a.b.c.d";

I am looking to create a generic type in TypeScript called StringToNestedObject that will take a string like this and return a nested object type as follows:

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

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

The closest solution I have come up with for StringToNestedObject is:

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

However, there are errors because [First] and [S] do not work due to:

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)

Click here for a TypeScript playground with the code.

(This task is inspired by how IndexedDB key paths use strings separated by periods to represent nested objects.)

Answer №1

Maybe I should have spent some more time experimenting before drafting my question :)

Here is a solution that 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 will be: { a: { b: string; } }

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

Interactive Example

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Customizing Angular Forms: Set formcontrol value to a different value when selecting from autocomplete suggestions

How can I mask input for formControl name in HTML? When the autocomplete feature is displayed, only the airport's name is visible. After users select an airport, I want to show the airport's name in the input value but set the entire airport obje ...

Asynchronous waiting waits not for async await

I'm currently working on a function that loops through an array and updates the model for each ID, then adds the result to another array. This is the code snippet I have: async function getSortedAnimals() { var i = 0; var sortedAnimals = []; id ...

Finding a solution to this issue in Angular will consistently result in a false outcome

Can anyone explain why I keep getting the error message "This condition will always return 'false' since the types 'typeof ChartType' and 'ChartType' have no overlap" whenever I try to compare charTypeEnum with ChartType.text? ...

Problems with installing ambient typings

I'm having trouble installing some ambient typings on my machine. After upgrading node, it seems like the typings are no longer being found in the dt location. Here is the error message I am encountering: ~/w/r/c/src (master ⚡☡) typings search mo ...

The upcoming construction of 'pages/404' page will not permit the use of getInitialProps or getServerSideProps, however, these methods are not already implemented in my code

Despite my efforts to search for a solution, I have not found anyone facing the same issue as me. When I execute next build, an error occurs stating that I cannot use getInitalProps/getServerSideProps, even though these methods are not used in my 404.tsx f ...

Receiving contextual information from Microsoft Teams within an Angular application integrated as a tab

I am currently integrating an Angular website into a Microsoft Teams tab. In order to perform certain computations, I need to retrieve the Team ID. To achieve this, I have recently added npm install --save @microsoft/teams-js. Below is the code snippet th ...

What is the proper way to integrate helmet.js with typescript?

Utilizing helmet from pure JavaScript according to the documentation is quite straightforward: const express = require('express') const helmet = require('helmet') const app = express() app.use(helmet()) However, I'm unsure how ...

Unable to pass property to child component

When trying to pass a string array prop in my child component, I encountered an error message: "Cannot destructure property 'taskList' of 'this.state' as it is null.". This error occurred when using destructurization. What am ...

Struggling with getting Typescript async/await to function properly

I'm experiencing an issue with async/await in TypeScript targeting es2017. Here is the code snippet that's causing trouble: My route.ts : method: 'POST', config: { auth: { strategy: &apo ...

I will not be accessing the function inside the .on("click") event handler

Can someone help me troubleshoot why my code is not entering the on click function as expected? What am I missing here? let allDivsOnTheRightPane = rightPane.contents().find(".x-panel-body-noheader > div"); //adjust height of expanded divs after addi ...

Is there a way to sort through an array based on a nested value?

Within an array of objects, I have a structure like this: "times": [{ "id" : "id", "name" : "place", "location" : "place", "hours" : [ {"day": " ...

Declaring a function in TypeScript triggers an error notification

I encountered a typescript error while running my code stating that "require" is not a function. To resolve this, I declared the function beforehand; however, a new typescript error now occurs saying "Modifiers cannot appear here." Can anyone assist me w ...

Is there a way for me to loop through an object without prior knowledge of its keys?

Upon receiving data from the server, it looks something like this: { "2021-10-13": { "1. open": "141.2350", "2. high": "141.4000", "3. low": "139.2000", "4. close& ...

What steps need to be taken in VSCode to import React using IntelliSense?

When I press Enter in that image, nothing seems to occur. I believed IntelliSense would automatically insert import React from 'react'; at the beginning of the file. https://i.stack.imgur.com/7HxAf.png ...

Attempting to send numerous identifiers in an API request

I encountered a problem while working on a function in Angular that involves pulling data from an API. My goal is to enhance a current segment to accommodate multiple IDs, but I face difficulties when attempting to retrieve more than one ID for the API que ...

"Despite modifying the ID in the response data of Angular MongoDB, the request data ID remains unchanged

Having trouble with managing requests and responses, specifically when a customer tries to add multiple items of the same product but in different sizes. The initial step involves checking if the ID exists by using a count and an if statement. If it exists ...

What is the best way to restrict the suggested values in a property depending on the value of another property?

I'm working on creating a third interface that depends on the value of properties from two other interfaces, while also introducing a unique third property. I've chosen not to extend the third property from the first two interfaces as it may not ...

An issue has occurred where all parameters for the DataService in the D:/appangular/src/app/services/data.service.ts file cannot be resolved: (?, [object Object])

Upon running the command ng build --prod, an error is encountered. Error in data.service.ts: import { BadInput } from './../common/bad-input'; import { AppError } from './../common/app-error'; import { Injectable } from '@angular ...

What is the best approach for managing _app.js props when transitioning from a page router to an app router?

Recently, in the latest version of next.js 13.4, the app router has been upgraded to stable. This update prompted me to transition my existing page router to utilize the app router. In _app.jsx file, it is expected to receive Component and pageProps as pr ...

Creating object-oriented designs in TypeScript: leveraging subclassing to account for differences in constructors

Working with ES6 classes and TypeScript to create a user interface, I have a base class named Control. I am looking for a way to create a Button, which is essentially an instance of Control with predefined properties. To achieve this, I have used Button as ...