Determine the data type of a property by referencing the data type of another property within an array of objects using TypeScript

I am working with a specific type of interface called Route that consists of name and path properties.

interface Route {
    name: string,
    path: string
}

const routes = [
    {
        name: "first",
        path: "/first"
    },
    {
        name: "second",
        path: "/second"
    }
] as const

My goal is to develop a function that can retrieve the path for a given route based on its name.

const to = <Routes extends ReadonlyArray<Route>, CurrentRoute extends Routes[number]>(routes: Routes, name: CurrentRoute["name"]): CurrentRoute["path"] => {
    // Implementation details are not important here
    return "" as CurrentRoute["path"]
}

const path = to(routes, "first")
// Currently returns a union instead of a string

What I need is for this function to accurately return a single string inferred from the corresponding object's name:

  • "/first" should be returned by TypeScript when calling the function with "first"
  • "/second" should be returned by TypeScript when calling the function with "second"
  • ...

The actual implementation of the function is trivial; what I am seeking is a solution within TypeScript's type system.

Link to reproduction

Answer №1

The issue with your version is the lack of an inference site for the CurrentRoute type argument. Unfortunately, generic types cannot be inferred from indexed access types like CurrentRoute["name"]. There was a pull request at microsoft/TypeScript#20126 that aimed to address this but did not get implemented.

To resolve this issue, you can directly associate the name property with a generic type parameter (let's call it N) and use it to compute the type for your CurrentRoute. Here is one way to achieve this:

const to = <R extends Route, N extends R["name"]>(
    routes: readonly R[], name: N): Extract<R, { name: N }>["path"] => {
    // Implementation details are irrelevant here
    return null!;
}

Since the order of elements in routes does not matter in your example, I have replaced your Routes type parameter representing the entire array with just R representing the union of its members. The type parameter N is constrained to R["name"], which is the union of name property types in R.

The return type utilizes the Extract<T, U> utility type to extract the member of the union with a name property of type N and then accesses its path property type.

Let's test if it works:

const path = to(routes, "first");
// const path: "/first"

const path2 = to(routes, "second");
// const path2: "/second"

Everything seems to be functioning correctly!

Link to Playground

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

I encountered a TypeScript error in React Native when attempting to use "className" with TypeScript

Although I've been using React for a while, React Native is new to me. I recently started using tailwind with import { View, Text } from "react-native"; import React from "react"; export default function Navigation() { return ...

Relocating the node_modules folder results in syntax errors arising

I encountered a perplexing syntax error issue. I noticed that having a node_modules directory in the same location I run npm run tsc resolves the issue with no syntax errors. However, after relocating the node_modules directory to my home directory, ~ , a ...

Creating dynamic routing functionality in Angular 8 allows for a more personalized and

I am struggling with setting up routing in Angular 8. Here is how I am trying to do it: 'company/:id/activity' 'company/:id/contacts' However, I am not receiving any params in the activatedRoute: this.activateRoute.params ...

What causes npm start to fail in Angular 6 after incorporating social login functionality?

I am currently working on integrating Social Login functionality into my app. I have attempted to incorporate the following: npm install --save angular-6-social-login-fixed npm install --save angular-6-social-login npm install --save angular-6-social-log ...

Having trouble accessing a custom factory within a directive in Angular using TypeScript

Having some trouble with my injected storageService. When trying to access it in the link function using this.storageService, I'm getting an undefined error. Any assistance on this issue would be greatly appreciated. module App.Directive { import ...

What steps can be taken for TypeScript to identify unsafe destructuring situations?

When working with TypeScript, it's important to prevent unsafe destructuring code that can lead to runtime errors. In the example below, trying to destructure undefined can cause a destructuring error. How can we ensure TypeScript does not compile suc ...

The error message "TypeError: 'results.length' is not an object" occurred within the Search Component during evaluation

Having trouble with a search feature that is supposed to display results from /api/nextSearch.tsx. However, whenever I input a query into the search box, I keep getting the error message TypeError: undefined is not an object (evaluating 'results.lengt ...

Basic library using babel, TypeScript, and webpack - Error: (...) is not a recognized function; within Object.<anonymous>

Recently, I encountered a strange issue while trying to bundle a simple function using babel, typescript, and webpack. You can find the example that is not working at this link. To test it, simply download the code, run npm/yarn install, npm/yarn run buil ...

Angular - Sharing data between components with response value

I am currently in the process of restructuring my project, focusing on establishing communication between unrelated components while also waiting for a return value from a function call. Imagine having component1 with function1() and component2 with funct ...

Exploring the canDeactivateFn syntax with Angular Documentation

As a first-year university student, I recently discovered that the canDeactivate() guard in Angular is deprecated, while the canDeactivateFn guard functions without any issues. Admittedly, navigating through official documentation is still new to me. From ...

Evaluation of button display based on certain conditions

I currently have two different render functions that display certain elements based on specific conditions. The first render function looks like this: private render(): JSX.Element { return ( <div> {this.props.x && this.state.y ...

"Choose one specific type in Typescript, there are no in-b

Need help returning an object as a fetch response with either the property "data" or "mes": { data: Data } | { mes: ErrMessage } Having trouble with TypeScript complaining about this object, let's call it props: if (prop.mes) return // Property &a ...

Exclude all .js files from subdirectories in SVN

In my typescript project, I am looking to exclude all generated JavaScript files in a specific folder from SVN. Is there a convenient command or method to achieve this for all files within the directory? ...

Learn how to generate specific error messages based on the field that caused the failure of the @Column({ unique: true }) Decorator. Error code 23505

Hey there! I'm currently facing an issue while trying to handle Sign Up exceptions in my code. I want to inform the user if their username OR email is already in use. Although using the decorator @Column({ unique: true}) allows me to catch error 23505 ...

Sequelize is not giving the expected model even after utilizing `include: [{ model: this.buildModel, required: true }]`

I've hit a roadblock trying to solve this problem. Despite my belief that I've correctly handled the migration, model definition, and query, I'm unable to retrieve the build in my iteration. Below are the models: SequelizeBuildModel.ts @Ta ...

Typescript: How to Ensure Tuple Type is Explicit and Not Combined

I have a code snippet that defines a person object and a function to get its values: const person = { name: "abc", age: 123, isHere: true }; const getPersonValues = () => { return [person.name, person.age, person.isHere]; }; const [n ...

Guide to importing a JavaScript module as any type without using a declaration file (d.ts)

Looking to bring a js module into my ts app. Is there a way to achieve this without creating a d.ts file? If not, how can it be declared as any in the d.ts file? Currently using //@ts-ignore to ignore the error. Appreciate any help! ...

Enhance the efficiency of writing the *.d.ts file

I have recently started diving into TypeScript with React and encountered a new concept called a .d.ts file. I am wondering if there is an established best practice for writing this file or if it's more of a developer preference. Can someone verify if ...

TypeScript raises an issue with a Vue component property that has been defined using vue-property-decorator

I have a Vue component with a property defined using a decorator: import { Component, Vue } from "vue-property-decorator" @Component({ props: { myId: String, }, }) class TestProp extends Vue { myFuncti ...

Issue arises when TypeScript attempts to verify the presence of an array element

I am facing an issue with the following array declaration: // Using const as I require it to be a specific type elsewhere const fruits = ["strawberry", "banana", "orange", "grapefruit"] as const; When attempting to ...