How can TypeScript generics be used to create multiple indexes?

Here is an interface snippet:

interface A {
    a1: { a11: string };
    a2: { a21: string };
    a3: { a31: string };
} 

I am looking to create a generic type object with indexing based on selected fields from interface A.

Here is the pseudo-code example:

type B<T1 extends keyof A, T2 extends keyof A> = {
    [P in T1]: A[T1];
    [P in T2]: A[T2];
}

Let's see how it can be used:

let var1: B<"a1", "a2"> = { a1: { a11: "Hello" }, a2: { a21: "World" } };

Now, var1 is an object with only fields: a1 and a2

Hope this helps! Thank you.

Answer №1

Using the Pick method can efficiently select specific fields from a type without needing to define a separate mapped type. It allows for selecting multiple fields at once:

interface A {
    a1: { a11: string };
    a2: { a21: string };
    a3: { a31: string };
} 
// Pick<A, "a1" | "a2"> <=> { a1: { a11: string }, a2: { a21: string } }
let var1: Pick<A, "a1" | "a2"> = { a1: { a11: "Hello" }, a2: { a21: "World" } };

If you frequently need to pick from type A, it's possible to create a dedicated type while maintaining flexibility with a single key parameter:

type B<TKey extends keyof A> = Pick<A, TKey>
let var1: B<"a1" | "a2"> = { a1: { a11: "Hello" }, a2: { a21: "World" } };

When working with types, it is recommended to utilize built-in methods like Pick instead of creating new mapped types. This simplifies understanding for team members as built-in methods are well-documented and easier to grasp.

It's important to note that the B type does not restrict users to picking only two fields from A</code. By using <code>never and unions, any number of keys can be selected from

A</code:</p>

<pre><code>// pick 2 fields
let var1: B<"a1", "a2"> = { a1: { a11: "Hello" }, a2: { a21: "World" } };
// pick 1 field
let var2: B<"a1", never> = { a1: { a11: "Hello" } };
// pick all 3
let var3: B<"a1" | "a2", "a3"> = { a1: { a11: "Hello" }, a2: { a21: "World" }, a3: { a31: "World" } }; 

Answer №2

Specific response for two inputs:

type NewType<T1 extends keyof A, T2  extends keyof A> = {
    [Property in T1 | T2]: A[Property];
}

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

How can I store various data types in a single array in TypeScript?

I have a scenario I need help with. Let's say we have two interfaces, Cats and Dogs. How can I create an array that can store both Cats and Dogs? interface Cats { name: string; age: number; } interface Dog { owner: string; } const cat1: Cat ...

I'm having trouble understanding why I can't access the properties of a class within a function that has been passed to an Angular

Currently, I have integrated HTML 5 geolocation into an Angular component: ... export class AngularComponent { ... constructor(private db: DatabaseService) {} // this function is linked to an HTML button logCoords(message, ...

Ways to dynamically authenticate in AuthGuard and return a true value

I am working on an auth guard that has multiple conditions, and I am looking for a way to dynamically return a true value. Here is the relevant code snippet: auth.guard.ts canLoad(route: Route, segments: UrlSegment[]): Observable<boolean>|Promise&l ...

I am experiencing difficulty in retrieving the content-disposition from the client

I am attempting to retrieve a .xlsx file that is generated on the backend using Spring Boot. I am able to retrieve headers on the frontend, which include the content-disposition as shown below. However, I am unable to access the content disposition in the ...

Guide to incorporating Bootstrap icons into an Angular application through programming techniques

Have you checked out the official bootstrap documentation for information on how to use their icons? https://i.stack.imgur.com/N4z2R.png I'm currently trying to understand the package and its usage. However, none of the options in the documentation ...

Dynamically apply classes in Angular using ngClass

Help needed with setting a class dynamically. Any guidance is appreciated. Below is the class in my SCSS file: .form-validation.invalid { border: 2px solid red } In my ts file, there's a variable named isEmailValid. When this variable is set to ...

I keep receiving multiple header errors from ExpressJS even though I am positive that I am only sending a single header

Can someone please help with the issue I'm facing in the code below: router.put("/:_id", async (req: Request, res: Response) => { try { // Create the updated artist variable const artist: IArtist = req.body; const updatedArt ...

What methods can be used to accurately display the data type with TypeOf()?

When working with the following code: const data = Observable.from([{name: 'Alice', age: 25}, {name: 'Bob', age: 35}]); console.log(typeof(data)); The type is displayed as Object(). Is there a way to obtain more specific information? ...

The proper method for retrieving FormData using SyntheticEvent

I recently implemented a solution to submit form data using React forms with the onSubmit event handler. I passed the SyntheticBaseEvent object to a function called handleSubmit where I manually extracted its values. I have identified the specific data I n ...

Leveraging the 'this' keyword in TypeScript

In my Javascript class, I used the 'this' keyword as shown below: if (this[this.props.steps[i].stepId].sendState !== undefined) { this.setState({ allStates: { ...this.state.allStates, [thi ...

When there is data present in tsconfig.json, Visual Studio Code does not display errors inline for TypeScript

After creating an empty .tsconfig file (consisting solely of "{ }"), Visual Studio Code immediately displays errors both inline and in the "problems" section. Interestingly, when I populate the tsconfig.json file with data, these errors disappear. Is there ...

Error: The promise was not caught due to a network issue, resulting in a creation error

I'm trying to use Axios for API communication and I keep encountering this error. Despite researching online and attempting various solutions, I am still unable to resolve the problem. Can someone please assist me? All I want is to be able to click on ...

Tips for Logging HTTP Communication Errors in Angular

When making an HTTP put call to update a record in my .Net MVC application, I have noticed that the controller's put logic is not being triggered as expected compared to other types of HTTP requests. I want to implement error handling by using the Ha ...

What is GraphQl indicating when it informs me that I neglected to send arguments for the mutation

My GraphQL schema consists of various mutations and queries. I believe that validation of mutations should only occur when I send mutation { ... } to the graphql server. However, currently, the server is informing me that I have not sent arguments for all ...

Angular 8: ISSUE TypeError: Unable to access the 'invalid' property of an undefined variable

Can someone please explain the meaning of this error message? I'm new to Angular and currently using Angular 8. This error is appearing on my console. ERROR TypeError: Cannot read property 'invalid' of undefined at Object.eval [as updat ...

Create a unique type in Typescript that represents a file name with its corresponding extension

Is there a way for me to specify the type of a filename field in my object? The file name will consist of a string representing the name of the uploaded file along with its extension. For instance: { icon: "my_icon.svg" } I am looking for a ...

What is the best way to retrieve the value of an input field in React when incorporating Material UI components?

I am working with a few radio input components that have been imported from material Ui react. Each radio input is wrapped in a FormControlLabel component. <FormControlLabel onClick={checkAnswerHandler} value={answer} control={<Radio color=&quo ...

The cell must be crafted with a styling attribute to determine its placement

While working on my web app using React, I encountered a console warning: react_devtools_backend.js:4012 Rendered cell should include style property for positioning. at Grid2 (http://localhost:5173/node_modules/.vite/deps/react-virtualized.js?v=b41cc5 ...

Contrasting the utilization of `typeof` with a constant and `enum` in TypeScript

Can you explain the distinction between using typeof with a constant and an enum in TypeScript? For example: const TYPE_A = 'a' const TYPE_B = 'b' type MyType = | typeof TYPE_A | typeof TYPE_B type Result = { name: string type ...

Unable to retrieve component name using React.Children

While working with react in the nextjs framework, I attempted to create my own dropdown component structured as follows: <Dropdown> <DropdownToggle>Action</DropdownToggle> <DropdownMenu> <DropdownItem>Menu 1</Dr ...