Is there a way to use dot notation in TypeScript for a string data type?

I'm currently in the process of developing a function API with a specific format:

createRoute('customers.view', { customerId: 1 });  // returns `/customers/1`

However, I am facing challenges when it comes to typing the first argument. This is my progress so far:

const uris = {
  customers: {
    view: '/customers/:customerId',
  },
  users: {
    list: '/users',
  }
};

const createRoute = (route: string, routeParams: { [key: string]: string }) => {
  /**
   * Splitting 'customer.view' into resource and action variables
   */
  const [ resource, action ] = route.split('.');

  /**
   * Here's where I encounter an error:
   *  
   *   Element implicitly has an 'any' type because expression of type 'string' 
   *   can't be used to index type '{ customers: { view: string; } }'.
   *
   */
  const uri = uris[resource]?.[action]


  // ... additional code for replacing the route parameter...
};

I comprehend the meaning behind the error message. Although the function signature accepts any string, it should be limited to valid keys within the uri object.

Furthermore, the secondary split operation depends on the first one due to its nested nature.

Is there a way to define these types?

Answer №1

Another approach is the following that allows you to achieve this:

createRoute(['customers', 'view'], {}); // compile
createRoute(['users', 'list'], {}); // compile
createRoute(['users', 'view'], {}); // DOESN'T compile: Type '["users", "view"]' is not assignable to type 'Route<ICustomerUri>'.
createRoute(['nota router'], {}); // DOESN'T compile: Type '"nota router"' is not assignable to type '"customers" | "users"'

Code:

interface ICustomerUri {
    customers: {
        view: string;
    };
}

interface IUsersUri {
    users: {
        list: string;
    };
}

type Route<T> = [keyof T, keyof T[keyof T]];

type Routers = Route<ICustomerUri> | Route<IUsersUri>;

interface IUris extends ICustomerUri, IUsersUri {}

const uris: IUris = {
    customers: {
        view: '/customers/:customerId',
    },
    users: {
        list: '/users',
    }
};

const createRoute = (route: Routers, routeParams: { [key: string]: string }) => {
    // your implementation
}

Playground Link

Answer №2

Here's a format that should suit your needs:

const resource = route.split('.')[0] as keyof typeof uris;
const action = route.split('.')[1] as keyof typeof uris[typeof resource];

Check it out on the Playground

Answer №3

Appreciate all the feedback from everyone. The solutions presented were either overly complicated or lacked proper type safety. In the end, I opted for a more straightforward approach:

const paths = {
  'products.view': '/products/:productId',
  'orders.list', '/orders',
};

type PathKey = keyof typeof paths;

const createPath = (path: PathKey, ...)

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

The Alert dialog in Shadcn will automatically close upon clicking the trigger from the dropdown menu

It seems like other people have encountered this issue, but they all used the alert dialog in the same file. I attempted to open the alert dialog using "" and included a dropdownmenuitem with 'delete' inside it. However, when trying to open the ...

Include quotation marks around a string in C# to convert it into JSON format

I am utilizing a service that operates with JSON format. However, the JSON data I am receiving does not include double quotes around keys and values. Here is an example of the data I have: [{name:{buyerfirstname:Randy, buyermiddlename:null, buyerlastnam ...

Issues with CSS Styling not being applied properly on mobile devices in a React App deployed on Heroku

The Dilemma My React app is deployed on Heroku using create-react-app for bundling. The backend is a Node.js written in Typescript with node version 10.15.3. Locally, when I run the site using npm start, everything works perfectly. However, when I view t ...

Error messages encountered following the latest update to the subsequent project

Recently, I upgraded a Next project from version 12 to 14, and now I'm encountering numerous import errors when attempting to run the project locally. There are too many errors to list completely, but here are a few examples: Import trace for requeste ...

Retrieve the array from the response instead of the object

I need to retrieve specific items from my database and then display them in a table. Below is the SQL query I am using: public async getAliasesListByDomain(req: Request, res: Response): Promise<void> { const { domain } = req.params; const a ...

What is the process for creating a PickByValue data type?

The TypeScript language comes with a built-in Pick type, which is defined as follows: type Pick<T, K extends keyof T> = { [P in K]: T[P]; }; If you were to create a custom PickByValue type, how would you implement it to achieve the following func ...

How to conceal duplicate items in Angular2

In my Angular 2/4 application, I am fetching data from a web API (JSON) and displaying it in a table. In AngularJS, I use the following code: <tbody ng-repeat="data in ProductData | filter:search | isAreaGroup:selectedArea"> <tr style="backgro ...

Tips for importing a library in a TypeScript file that expands a JavaScript prototype

After following the instructions provided in this question, I am experimenting with integrating Moment.js to enhance the capabilities of the Date prototype within a TypeScript project. The process of extending the Date prototype appears successful, as out ...

What is the best way to dynamically insert values into a JSON object?

I'm currently working with a JSON object in Angular and I need to dynamically add values that the user enters. Despite searching extensively, I haven't found a straightforward method to achieve this. I simply want to understand how to append key- ...

How do I create a generic function in TypeScript that adjusts its behavior based on the input argument?

Is there a way to create a generic function that can accept generic arguments like Data<string, number>? Take a look at this code snippet: interface Data<T,R> { a:T; c:R; } function foo( data: Data<string, number> ){ return t ...

Incorporating a component specified in a .jsx file into a TypeScript file

We recently acquired a react theme for our web application, but ran into issues transpiling the components. After resolving that problem, we are now facing type-related challenges. It seems that TypeScript is struggling because the props do not have a def ...

What's stopping me from using useState() to assign API data to an array?

I have a question regarding my app that makes use of the Movies API. I am making an API request and then passing the data to an array using the useState hook. Here is a snippet of my code: const App = () => { type MovieType = { rate: string, ...

Utilizing React Bootstrap with TypeScript for Styling Active NavItem with Inline CSS

Is it possible to change the background color of the active NavItem element to green using inline CSS in React Bootstrap and React Router Dom? I am currently using TypeScript 2.2 and React. If not, should I create a CSS class instead? Here is the code sni ...

Manipulate classes by adding or removing them on click events in Angular

I am struggling to implement the angular ngClass for adding a class with a click event. Despite calling a function that should change the value of the "isExpandedConectivity" variable when clicking on the "li" element, it doesn't seem to work as expec ...

Guide to executing various datasets as parameters for test cases in Cypress using Typescript

I am encountering an issue while trying to run a testcase with multiple data fixtures constructed using an object array in Cypress. The error message states: TS2345: Argument of type '(fixture: { name: string; sValue: string; eValue: string}) => vo ...

TS: How can we determine the type of the returned object based on the argument property?

Assume we have the following data types type ALL = 'AA' | 'BB' | 'CC'; type AA = { a: number; }; type BB = { b: string; }; type CC = { c: boolean; }; type MyArg = { type: ALL }; I attempted to create a mapping between type n ...

Deleting an element from an object in TypeScript

Is there a way in TypeScript to exclude certain elements (e.g. 'id') from an object that contains them? ...

Trouble with Styling React-Toastify in TypeScript: struggling to adjust z-index in Toast Container

Currently in the process of developing a React application utilizing TypeScript, I have incorporated the React-Toastify library to handle notifications. However, encountering some challenges with the styling of the ToastContainer component. Specifically, ...

Unleashing the power of joint queries in Sequelize

Project.data.ts import { DataTypes, Model, CreationOptional, InferCreationAttributes, InferAttributes, BelongsToManyGetAssociationsMixin, BelongsToManySetAssociationsMixin, BelongsToManyAddAssociationsMixin } from 'sequelize'; import sequelize fr ...

Using Angular's filter pipe to search within a nested array

We are attempting to implement an angular pipe for filtering a list of sub-items, with the goal of removing parent items if there are no child items present. Here is the HTML code snippet we are using: <div class="row border-bottom item" *n ...