Data types for keys and values in TypeScript

interface A { a?: number };
interface B { a?: string };

function replicate<
    Source extends object,
    Destination extends { [key in keyof Source]?: (1) }
>(
    source: Source,
    key: keyof Source,
    destination: Destination,
    converter: (value: (2)) => (3) 
) {
    if (source[key] !== undefined) {
        destination[key] = converter ? converter(source[key]) : source[key];
    }
}

const a: A = { a: 123 };
const b: B = {};

replicate(a, "a", b, (value) => value.toString());

In the sample above, what fits for the following placeholders:

  • (1) - data type of value in Destination related to the corresponding key in Source.
  • (2) - information type in Source associated with the specified key in parameter key.
  • (3) - data type in Destination linked to the specified key in parameter key.

Answer №1

To ensure accurate key passing, an additional type parameter is needed to represent the specific key being passed in. This parameter will be automatically determined as a string literal type based on the value passed into the key parameter. By introducing this new type, we can utilize type queries to access the exact property within the Source and Destination types.

In addition, since our main focus lies on the particular K key, we can incorporate it while defining the Destination type by specifying its presence (instead of mandating that Destination must contain all keys from Source). As we are not concerned with the destination property's type, but rather with its existence and the fact that the transformer function should return a value of the same type as this property, we can simply designate the type of the property in Destination as unknown.

interface A { a?: number };
interface B { a?: string };

function copy<
    K extends keyof Source, // Additional type parameter
    Source extends object,
    Destination extends { [destinationKey in K]?: unknown } // Can be any type without much concern, solely the existence of key K matters
>(
    source: Source,
    key: K, // Key is of type K
    destination: Destination,
    transformer: (value: Source[K]) => Destination[K] // Utilizing K to define the relationship between Source and Destination property types
) {
    if (source[key] !== undefined) {
        destination[key] = transformer ? transformer(source[key]) : source[key];
    }
}

const a: A = { a: 123 };
const b: B = {};

copy(a, "a", b, (value) => value.toString());
copy(a, "a", b, (value) => value); /// error

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

Casting types of objects in Angular2 using TypeScript

Trying to extract the model object from the JSON obtained through a http response call. The following JSON represents the body of the http response, { "dataType": "RWSupplier", "partyName": "Lifecare Pharmaceuticals", "partyShortName": null, "partySecon ...

Lambda functions that support multiple languages coexisting in a single directory

As I have lambda functions written in both Typescript and Java, I am contemplating whether to store them all together in a single directory or separate them based on the language. Our infrastructure deployment is done using terraform and CI/CD with Jenki ...

Adding a Third-Party JavaScript Plugin to Angular 7

I've been attempting to integrate the read-excel-file JavaScript plugin into my Angular 7 project. Despite following all the methods recommended on various websites, I have yet to succeed. Could anyone provide a better solution? declare var readXlsx ...

Undefined type stack in C

While attempting to implement a stack using a linked list structure, I encountered an issue when compiling `main`. The error message pointed to a problem within `"main.h"` at "`stack* head`"... error: unknown type name ‘stack’ unsigned long int ...

The method takes in an array of user names along with an HTTP request for each, then it will generate an observable array of user objects as output

I need to retrieve an array of user objects from a non-observable array of usernames (string[]). I am looking for a method that can fetch each user object through getUser(username) (HTTP GET request from Angular in-memory web API) for each provided usernam ...

Is there a way to automatically determine the parameters of a constructor to match the default class type in TypeScript

I need a function in a class that can utilize a type from constructor arguments, but I am unsure how to achieve this. class CustomClass<Type1, Type2=any>{ a: string = 'a' constructor(private readonly parameters: { attributes: Type ...

Anticipated the object to be a type of ScalarObservable, yet it turned out to be an

When working on my Angular project, I utilized Observables in a specific manner: getItem(id): Observable<Object> { return this.myApi.myMethod(...); // returns an Observable } Later, during unit testing, I successfully tested it like so: it(&apos ...

The MUI component received props that were not defined

I created a customized MUI card with the intention of applying a dark background when the darkBg prop is passed. However, I've encountered an issue where despite passing darkBg as true, the card's background remains white. To troubleshoot, I atte ...

Angular 6: The importance of access modifiers when injecting services

As I make my way through the tutorial, an interesting scenario has arisen. I've noticed that when injecting a service into my component without specifying an access modifier, it results in an error as shown below. However, adding either "private" or ...

Display a fixed three levels of highchart Sunburst upon each click in Angular8

Looking to create a dynamic sunburst highchart that displays three levels at a time while allowing interactive drilling. For instance, if there are 5 levels, the chart should initially show the first three levels. When clicking on level 3, levels 2, 3, and ...

Utilizing NPM Workspace Project in conjunction with Vite to eliminate the necessity of the dist folder during the Vite build process

I am currently working on a project that involves a module using full path exports instead of index files. This project is divided into 2 NPM workspaces: one called core and the other called examples. The challenge I am facing is avoiding long import pat ...

Issue with Ionic 3 subscribes triggering repeatedly

I've been struggling with the code for an Ionic taxi app for a few weeks now. My main issue is that whenever the page loads, the subscription gets triggered multiple times along with other functions within it. The same problem occurs when any travel i ...

Conflicting Angular controller names within different modules

I'm facing an issue where two modules (A and B) with controllers of the same name are conflicting when imported into module C. Is there a recommended solution to prevent this conflict, such as using a naming convention like "module.controller" for ea ...

Is there a way to conditionally redirect to a specific page using NextAuth?

My website has 2 points of user login: one is through my app and the other is via a link on a third-party site. If a user comes from the third-party site, they should be redirected back to it. The only method I can come up with to distinguish if a user is ...

Error with declaring TypeScript class due to private variable

When defining a TypeScript class like this: export class myClass { constructor(public aVariable: number) {} private aPrivateVariable: number; } and trying to initialize it with the following code: let someVar: myClass[] = [{ aVariable: 3 }, { aV ...

"Encountered an error: 'Invalid private class xy' in the process of constructing an Angular library

Currently, I am in the process of creating an npm package using Angular. In the midst of building the library, I encountered the following error: An unexpected issue with the private class MyLibComponent has surfaced. While this class is accessible to us ...

Changing the way in which text is selected and copied from a webpage with visible white space modifications

After working on developing an HTML parser and formatter, I have implemented a new feature that allows whitespace to be rendered visible by replacing spaces with middle dot (·) characters and adding arrows for tabs and newlines. https://i.sstatic.net/qW8 ...

Steps to make ng-packagr detect a Typescript type definition

Ever since the upgrade to Typescript 4.4.2 (which was necessary for supporting Angular 13), it appears that the require syntax is no longer compatible. Now, it seems like I have to use this alternative syntax instead: import * as d3ContextMenu from ' ...

Missing from the TypeScript compilation are Angular5's polyfills.ts and main.ts files

Here is the structure of my Angular5 project. https://i.stack.imgur.com/tmbE7.png Within both tsconfig.app.json and package.json, there is a common section: "include": [ "/src/main.ts", "/src/polyfills.ts" ] Despite trying various solu ...

The Select element in Next.js needs to have an accessible name - it must have a title attribute for improved accessibility

Just starting out with Next.js and Typescript. I'm in the process of rebuilding an app using Next.js, but I've hit a roadblock when trying to split pages and components. The error message that keeps popping up is "Select element must have an acce ...