Creating a TypeScript generic type for the "pick" function to define the types of values in the resulting object

I am facing an issue while writing the type for the pick function. Everything works smoothly when picking only one key or multiple keys with values of the same type. However, if I attempt to pick a few keys and their values are of different types, I encounter an error. I am uncertain about where I might have made a mistake.

Thank you for taking the time.

export interface Mapper<T = any, R = any> {
  (arg: T): R;
}


export function pick<O, T extends keyof O>(keys: T[], obj?: O): { [K in T]: O[T] };

export function pick<T>(keys: T[], obj?: never): Mapper;

export function pick<O, T extends keyof O>(keys: T[], obj?: O) {
  const picker: Mapper<O, { [K in T]: O[T] }> = _obj =>
    keys.reduce((acc, key) => {
      if (key in _obj) {
        acc[key] = _obj[key];
      }
      return acc;
    }, {} as O);

  return obj ? picker(obj) : picker;
}

const obj = { someKey: 'value', otherKey: 42, moreKey: ['array value'] };

const newObj = pick(['otherKey'], obj);
//OK. TS type for newObj is {otherKey: number}

const n: number = newObj.otherKey;
// OK

const otherNewObj = pick(['otherKey', 'someKey'], obj);
//not really OK. TS type for otherNewObj is {otherKey: number | string, someKey: number | string}

const m: number = otherNewObj.someKey;
// Error. Type string | number is not assignable to the number

Answer №1

Your mapped type has an error; consider using O[K] instead of O[T] to obtain { [K in T]: O[K] }. This ensures the type corresponds to each key K, rather than all properties in the T union.

You may also want to utilize Pick since it is homomorphic and can retain modifiers like readonly and optional.

The usage of obj?: never might not have the intended effect as anything is assignable to

never</code. It's better to exclude the parameter from that particular overload:</p>

<pre><code>export function pick<O, T extends keyof O>(keys: T[], obj?: O): Pick<O, T>;
export function pick<T>(keys: T[]): Mapper;
export function pick<O, T extends keyof O>(keys: T[], obj?: O) {
    //....
}

Check it out on 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

Forming a distinct array from a collection of objects

Describing demoList: demoList = [ { id: 1, validFrom: "2019-06-01T00:00:00", validTo: "2020-06-17T00:00:00", xxxM: 50, xxxN: 2.2, xxxQ45: 2, xxxQ100: 1.65, xxxQ125: null, xxxQ150: null, xxxQ2 ...

What is the best way to display a loading screen while simultaneously making calls to multiple APIs?

I'm currently working with Angular 8 to develop an application that retrieves responses from various APIs for users. The application is designed to simultaneously call multiple APIs and I require a loading indicator that stops once each API delivers a ...

Typescript Error: Trying to access a property that is undefined

I am a beginner in typescript and believe that the issue I am facing is related to typescript. Currently, I am working on an Ionic app where I have a function setwall() being called from home.html. The setwall() function is defined in home.ts. However, whe ...

Error message: The object is not visible due to the removal of .shading in THREE.MeshPhongMaterial by three-mtl-loader

Yesterday I posted a question on StackOverflow about an issue with my code (Uncaught TypeError: THREE.MTLLoader is not a constructor 2.0). Initially, I thought I had solved the problem but now new questions have surfaced: Even though I have installed &apo ...

Finding the identifier for resources through excluding external influences

I am currently facing an issue with the full calendar plugin. In my set up, I have 3 resources along with some external events. The problem arises when I try to drop an external event onto the calendar - I want to retrieve the resource id from which the ev ...

Creating a Node server exclusively for handling POST requests is a straightforward process

I'm looking to set up a Node server that specifically handles POST requests. The goal is to take the data from the request body and use it to make a system call. However, my current setup only includes: var express = require('express'); var ...

Need help troubleshooting a problem with the <tr><td> tag in vue.js?

I have a table that updates when new data is created, and I want to achieve this using Vue.js I decided to explore Vue.js Components and give it a try. <div id="app1"> <table class="table table-bordered"> <tr> ...

Unable to resolve the "Error: posts.map is not a function" issue

I am currently developing a social media-like web application. One of the features I'm working on is to display all posts made by users. However, when I run my code, it doesn't show anything and I get an error in the console that says "Uncaught T ...

How to toggling array object value in React or Redux state using Javascript/ES2015

If we have a structure like this: export default class Questions extends Component { state = { questions: [ {value: 'value one, required: true}, {value: 'value two, required: true}, {value: 'value two, required: tru ...

Encountering an issue with postman where properties of undefined cannot be read

I am facing an issue while trying to create a user in my database through the signup process. When I manually enter the data in the create method, it works fine as shown below: Note: The schema components are {userName:String , number:String , email:Stri ...

Using jQuery to update a specific item in a list

My current project involves developing an Image Gallery app. It uses <img> tags within li elements. The code snippet is as follows: var $slideR_wrap = $(".slideRoller_wrapper"); var $slidesRoller = $slideR_wrap.find(".slidesRoller"); var $slideR ...

Script that was generated dynamically is failing to run

I have a situation where I am adding a script tag, along with other HTML content, to my current document after making an AJAX call. However, the script is not executing as expected. //Function to handle response function(responseText){ document.getEle ...

Utilizing Bresenham's line drawing algorithm for showcasing box contours

I am seeking a similar behavior to what is demonstrated on , but with some modifications to the boxes: div { display: inline-block; width: 100px; height: 100px; border: 1px solid black; cursor: pointer; } div.selected, div:hover { backgroun ...

Deactivate Mongoose connection in Node.js after completing tasks

Here is a mongoose script I have been using to connect to the local database and perform some operations. However, I am facing an issue with disconnecting the connection after use. const mongoose = require('mongoose'); const db = mongoose.connec ...

Tips for distinguishing between the different values

Greetings! I am currently utilizing this code snippet to retrieve values from a Java class. Upon getting the data from Java, it triggers an alert displaying two values separated by spaces. My next goal is to split the values into two separate entities an ...

Exploring the process of implementing smooth transitions when toggling between light and dark modes using JavaScript

var container = document.querySelector(".container") var light2 = document.getElementById("light"); var dark2 = document.getElementById("dark"); light2.addEventListener('click', lightMode); function lightMode(){ contai ...

How do you retrieve an element using its tag name?

Just delving into the world of API's here. Working on a project involving loading a DIV with a bunch of links that I need to repurpose. Managed to disable the default onclick function, now trying to figure out how to save the "innerHTML" attribute of ...

Route all Express JS paths to a static maintenance page

Need help with setting up a static Under construction page for an Angular Web App with Express Node JS Backend. I have a function called initStaticPages that initializes all routes and have added a new Page served via /maintenance. However, when trying to ...

The parent-child relationships in MongoDB

In my Meteor application, I have created two collections: ActivityCards and Users. Inside the ActivityCard collection, there is a reference to the User like this: { "_id" : "T9QwsHep3dMSRWNTK", "cardName" : "Guntnauna", "activitycardType" : 1 ...

Combining multer, CSRF protection, and express-validator in a Node.js environment

Within my node.js application, I am utilizing an ejs form that consists of text input fields in need of validation by express-validator, an image file managed by multer, and a hidden input housing a CSRF token (a token present in all other forms within the ...