Mapping an array of keys to an array of properties using Typescript

Is there a way to achieve the following:

type A = { a: string; b: number; c: boolean };
type B = ["b", "a"];

type C = MapProps<A, B> ?? // [number, string]

The solution I have currently is:

type C = {[key in B[number]]: A[key]}

However, this results in an object whereas my goal is to eliminate the keys and retain only the values as a tuple, maintaining the same order as B. Is there a concept similar to Object.values() at the type level?

Answer №1

To solve this problem, we will implement recursive conditional types. The process is outlined as follows:

During each iteration, we extract the first element (K) from the B array and save A[K] in a result array (R). This procedure continues until the B array is empty, at which point we return the final result array.

Here is the implementation code:

type MapProps<
  T,
  Keys extends PropertyKey[],
  Result extends unknown[] = []
> = Keys extends [
  infer First extends keyof T,
  ...infer Rest extends PropertyKey[]
]
  ? MapProps<T, Rest, [...Result, T[First]]>
  : Result;

The type PropertyKey encompasses any key type such as string, number, or symbol.

We utilized the infer keyword to separate the first element and remaining elements in the array type.

For testing purposes, consider the following example:

type A = { a: string; b: number; c: boolean };
type B = ["b", "a"];

type C = MapProps<A, B>; // [number, string]

Try it out on the TypeScript 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

The element 'flat' is not found within the specified type

My challenge involves utilizing the flat() method in a TypeScript script. In my tsconfig.json file, I have set the target to es2017 and defined an interface for the input variable. However, I keep encountering this error message: Property 'flat' ...

Creating Class Names Dynamically in Angular 2 Using ngFor Index

Encountering an issue while trying to generate a dynamic class name based on the ngFor loop index in Angular 2. Due to restrictions, I had to use a specific syntax as Angular 2 does not support ngFor and ngIf together on the same element. Given this setup ...

Deactivate the Mention and Hash tag in ngx-linkifyjs

I am currently utilizing ngx-linkifyjs to automatically convert URLs in text to clickable hyperlinks. However, I am facing an issue where it is also converting # and @ tags into links. Is there a way to prevent the conversion of # and @ while maintain ...

What is the reason behind TypeScript failing to provide type safety in a generic higher order component which introduces extra properties into React components?

I'm currently working on developing a versatile higher order component, but have encountered an issue with type safety not being enforced. Interestingly, when attempting the same implementation without using generics, the type safety is verified as ex ...

Using Typescript: Generate keys in function return depending on parameter

Currently in the process of developing an SDK for a Rest API that includes an embed request parameter to fetch additional resources and add them to the response. I am exploring if there is a way, using Typescript, to extract these embed parameters while de ...

Issue regarding custom CSS implementation in Angular project

Being a French speaker, I apologize in advance for any mistakes I might make. I am also fairly new to Angular, so if you could provide detailed explanations in your responses, it would be greatly appreciated. Thank you. I am trying to import a custom CSS ...

Troubleshooting: The canvas texture in Phaser 3's Update() function is not functioning

I've been attempting to transform this tutorial into Phaser 3: but have encountered an issue with the update() function not working. I also tried using the refresh() function, but that didn't solve the problem either. In my file a.ts, I have cre ...

Encountering crashes while initializing the router in the constructor of a service in Angular 4.3

I've been scratching my head over this problem. It seems like I'm overlooking something simple. Let me show you what's inside my home.component.ts file: import { Component, OnInit } from '@angular/core'; import { AuthService } f ...

Is it possible for me to employ T extends Contravariant<any> to effectively restrict a generic type to a union of Contravariants

Let's begin by clarifying some terms: type Contravariant<T> = (t: T) => void; declare let cNum: Contravariant<number>; declare let cStr: Contravariant<string>; Now, suppose I wish to create a function that accepts an array of the ...

The TypeScript namespace does not exist or cannot be located

Currently, I am working on coding in TypeScript. The specific code pertains to an Angular 2 application, but the main focus of my inquiry lies within TypeScript itself. Within my project, there are certain files that contain various models, such as the exa ...

The issue lies within typescript due to process.env.PORT being undefined

I am a newcomer to working with TypeScript. Even after importing and using the dotenv package, I am still encountering issues with getting undefined values. Do I need to declare an interface for the dotenv variables? import express,{Application} from &apo ...

Error message: Unable to retrieve parameter value from Angular2 ActivatedRoute

I am attempting to showcase the value of the activated route parameter on the screen, but I am facing difficulties. In the initial component, my code looks like this: <ul *ngFor="let cate of categories;"> <li (click)="onviewChecklists(cate.id) ...

Tips for utilizing ngModel within *ngFor alongside the index?

Currently, I am dynamically generating mat-inputs using *ngFor. My goal is to store each value of [(ngModel)] in a separate array (not the one used in *ngFor) based on the index of the *ngFor elements. Here's my implementation: <div *ngFor="let i ...

How can I combine multiple styles using Material-UI themes in TypeScript?

There are two different styles implementations in my code. The first one is located in global.ts: const globalStyles = (theme: Theme) => { return { g: { marginRight: theme.spacing(40), }, } } export const mergedStyle = (params: any) ...

Whenever signing in with Next Auth, the response consistently exhibits the values of "ok" being false and "status" being 302, even

I am currently using Next Auth with credentials to handle sign-ins. Below is the React sign-in function, which can be found at this link. signIn('credentials', { redirect: false, email: email, password: password, ...

Transforming an array of flat data into a hierarchical tree structure

I'm facing a challenge with my script. I have an Array of FlatObj and some rules, and I need to create a converter function that transforms them into TreeObj. The Rules are: If an object has a higher depth, it should be a child of an object with a l ...

Is there a way to make a peer dependency optional in a project?

In the process of developing module A, I have implemented a feature where users can choose to inject a Winston logger into my module. As a result, winston becomes a peer dependency. However, when attempting to include module A in another module without th ...

The module 'contentlayer/generated' or its type declarations are missing and cannot be located

Currently running NextJS 13.3 in my application directory and attempting to implement contentlayer for serving my mdx files. tsconfig.json { "compilerOptions": { ... "baseUrl": ".", "paths" ...

Tips on passing an object as data through Angular router navigation:

I currently have a similar route set up: this.router.navigate(["/menu/extra-hour/extra-hours/observations/", id]) The navigation is working fine, but I would like to pass the entire data object to the screen in order to render it using the route. How can ...

What is preventing me from accessing a JavaScript object property when using a reactive statement in Svelte 3?

Recently, while working on a project with Svelte 3, I encountered this interesting piece of code: REPL: <script lang="ts"> const players = { men: { john: "high", bob: "low", }, }; // const pl ...