Steps for constructing an object literal with a property designated as the `keyof` type

Struggling to articulate my question, here is a simplified code snippet outlining what I aim to accomplish.

class Example<T, TId extends keyof T> {
  public create(id: T[TId]): T {
    return {
      [TId]: id, // Encounter an error at this point. Objective is to assign the value `id` to property `TId`.
    } as T;
  }
}

interface Person {
  id: number;
}

interface Place {
  cityName: string;
}

new Example<Person, 'id'>().create(123); // Intention is to receive { id: 123 }
new Example<Place, 'cityName'>().create('New York'); // Expecting { cityName: 'New York' }

Error message:

Conversion of type '{ [x: number]: T[TId]; }' to type 'T' may be problematic due to lack of overlap between the two types. If intentional, convert the expression to 'unknown' first. Instantiation of 'T' could result in an incompatible type with '{ [x: number]: T[TId]; }'.ts(2352)

Answer №1

Unfortunately, achieving what you are attempting to do purely with types is not possible. The issue lies here:

new Test<A, 'id'>().create(123); // Want to get { id: 123 }

When this code compiles to JavaScript, it looks like this:

new Test().create(123);

As you can see, it becomes impossible to return an object with the correct key because the type parameter ('id') does not exist in the compiled code. Type information is not retained at runtime.

To resolve this issue, you must change your design and pass 'id' as a string parameter to either create or Test(). For example:

class Test<T extends object, TId extends keyof T = keyof T> {

  constructor(private readonly key: TId) { }

  public create(value: T[TId]): T {
    return { [this.key]: value } as T;
  }
}

interface A {
  id: number;
}

interface B {
  fileName: string;
}

new Test<A>('id').create(123); // Returns { id: 123 }
new Test<B>('fileName').create('file'); // Returns { fileName: 'file' }

This way, the code infers TId automatically, accomplishes the desired outcome, and ensures that only the correct key names and values are used (trying to use filePath as a key or passing a number for fileName will result in compilation errors).

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

Obtain a filtering dropdown list directly from the database within Ag-grid

Currently in my interface, I am attempting to implement a filter for the FOLDER column. This filter is supposed to retrieve data from the database and present it in a dropdown checkbox within that column. The filtering should be based on the selected data. ...

What Type of state does Typescript expect in React?

Whenever I attempt to pass the state in my TypeScript-based React application using any to a function, I encounter a tslint error. no-any: The use of 'any' for type declaration compromises type safety. It is recommended to replace it with a mo ...

Transforming XML into Json using HTML string information in angular 8

I am currently facing a challenge with converting an XML document to JSON. The issue arises when some of the string fields within the XML contain HTML tags. Here is how the original XML looks: <title> <html> <p>test</p> ...

The CSS formatting is not being properly applied within the innerHTML

I have a scenario where I am trying to display a Bootstrap card using innerHTML in my TS file, but the styles are not being applied to this content. I suspect that the issue might be because the styles are loaded before the component displays the card, cau ...

The specified type argument is not compatible with the ObservableInput<any> type

Struggling with an issue where the argument type (key:string) => Observable | PayloadType | is causing problems when trying to assign it to a parameter of type '(value: string, index: number) => ObersvableInput' return action$.pipe( fil ...

An issue has been identified with React's HTML input maxLength feature where it does not display an error

Within my form, I have an input field that currently does not include validation for a maximum length. <input type="text" className="form-control" id="company" onBlur= ...

"Exploring the process of making a REST call from an Angular TypeScript client to

I'm currently developing a Sessions Server for a project at work. My dilemma lies in the fact that I'm struggling to find resources on how to make JavaScript HTTP calls from a server running with http.createServer() and server.listen(8080, ...) ...

The Azure GraphQL serverless function encountering an issue with the Cosmos DB connection, displaying an

After developing a serverless GraphQL API function using Azure functions and connecting it to Cosmos DB, I have encountered an issue with "Invalid URL" that has been puzzling me for a week. Despite running the graphql function locally without any problems, ...

When performing an arithmetic operation, the right operand must be a data type of 'any', 'number', 'bigint', or an enumeration type

My JavaScript code needs to be converted to TypeScript for proper functionality. categoryAxis.renderer.labels.template.adapter.add("dy", function(dy, target) { if (target.dataItem && target.dataItem.index % 2 === 0) { return dy + 25; } ...

Issue with my TypeScript modules TS2307: Module not found

For my latest project, I decided to use the aurelia-typescript-skeleton as the foundation. To enhance it, I created a new file called hello.ts in the src folder. export class Hello { sayHello(name:string) : string { return 'Hello ' + name; ...

Troubleshooting issue: Webpack dev server's Hot Module Replacement not functioning correctly when

I've been working on a Vue 2 application that is mostly JavaScript, and now I am looking to incorporate some new TypeScript modules and components into it. Everything runs smoothly when I start the webpack dev server. However, whenever I make a chang ...

While attempting to utilize npm install, I encounter an error on a discord bot stating "msvsVersion is not defined."

Struggling with self-hosting a TypeScript discord bot, the setup process has been a puzzle. It's supposed to generate a build directory with an index.js file, but it's unclear. Installed Visual Studio Build Tools 2017 as required, yet running npm ...

Angular 2 - Ensuring service executes only when boolean condition is met

I am currently dealing with a navigation menu that utilizes the ng2-page-scroll module. When scrolling through the page using hashtag links, I encountered an issue. If I navigate across routes, there is a delay in loading the data. As a result, the servic ...

Enhance your TypeScript React development with NeoVim

As a newcomer to vim, I decided to test my configuration with react and typescript. To do this, I created a simple demo app using the command npx create-react-app demo --template typescript. Next, I opened the directory in neovim by running nvim .. However ...

Exploring Angular2: The Router Event NavigationCancel occurring prior to the resolution of the Route Guard

My application has routes protected by an AuthGuard that implements CanActivate. This guard first checks if the user is logged in and then verifies if certain configuration variables are set before allowing access to the route. If the user is authenticated ...

Discover the step-by-step guide to setting up forwarding in React Router 5

Just diving into the world of React and TypeScript. I'm working with a component called Err. Is there a way to redirect it using React Router 5? import React, { FC, Fragment, useEffect } from "react"; const Err: FC<{ error: string }> = ({ erro ...

nodemon failing to automatically refresh files in typescript projects

I am currently developing an app using NodeJs, express, typescript, and nodemon. However, I am encountering an issue where the page does not refresh when I make changes to the ts files. Is there a way for me to automatically compile the ts files to js an ...

Issue with Angular filtering when utilizing pipe and mapping the response

Code snippet from shop.service.ts getProducts(brandId?: number, typeId?: number) { let params = new HttpParams(); if (brandId){ params = params.append('brandId', brandId.toString()); } if (typeId){ params = params.append('typeId', ...

Having trouble organizing the date strings in the material table column

In my Angular application, I have a material table with multiple columns that I am sorting using matSort. While I can successfully sort the last two columns in ascending or descending order, I am facing an issue with the first column which contains date va ...

Errors occur when trying to utilize an enum as a generic type in Typescript that are not compatible

Take a look at the code snippet provided. The concept here is that I have different provider implementations that extend a base provider. Each provider requires a settings object that is an extension of a base settings object. Additionally, each provider c ...