Explain a TypeScript function that takes an object as input and returns a new object with only the

Check Playground

What's the best way to define a type for this specific function? The inputObject should contain all keys from the enablePropertiesArray and may have additional ones. The function is expected to return a copy of the inputObject, inclusive only to the keys mentioned in the enablePropertiesArray.

export const createValidObject = <
  T extends string,
  IO extends { [K in T]?: unknown } & Record<string, unknown>,
  OO = { [K in T]?: IO[K] }
>(
  inputObject: IO,
  enablePropertiesArray: T[]
): OO => {
  let result: { [K in T]?: IO[K] } = {};
  enablePropertiesArray.forEach((property: T) => {
    if (Object.prototype.hasOwnProperty.call(inputObject, property)) {
      result[property] = inputObject[property];
    }
  });
  return result; //Type '{ [K in T]?: IO[K] | undefined; }' is not assignable to type 'OO'. 'OO' could be instantiated with an arbitrary type which could be unrelated to '{ [K in T]?: IO[K] | undefined; }'.(2322)
};

// Tests

const inObject = {
  "key1": "value1",
  "key2": "value2",
  "key3": "value3",
  "key_excess": "value4",
}

const enabledKeys = ['key1', 'key2', 'key3']

const newObj = createValidObject(inObject, enabledKeys) 
// newObj = {
//   "key1": "value1",
//   "key2": "value2",
//   "key3": "value3",
// }

// type NewObj = {
//   "key1": string,
//   "key2": string,
//   "key3": string,
// }

Answer №1

My take on this.

Link to Playground

The key modification here is turning T into an array rather than a single type. Additionally, the input types in the example were adjusted to as const to prevent loss of type information.

function createValidObject<IO, T extends readonly (keyof IO)[]>(inputObject: IO, enablePropertiesArray: T): { [K in T[number]]: IO[K] } {
  const result = {} as { [K in T[number]]: IO[K] };
  for (const property of enablePropertiesArray) {
    if (Object.prototype.hasOwnProperty.call(inputObject, property)) {
      result[property] = inputObject[property];
    }
  }
  return result;
}
const inObject = {
  "key1": "value1",
  "key2": "value2",
  "key3": "value3",
  "key_excess": "value4",
} as const;

const enabledKeys = ['key1', 'key2', 'key3'] as const;

const newObj = createValidObject(inObject, enabledKeys);
// const newObj: {
//     key1: "value1";
//     key2: "value2";
//     key3: "value3";
// }

Answer №2

Here are the modifications I made to your code in order to get the example functioning correctly:

function constructValidObject<T extends string, 
    InputObj extends { [Key in T]?: unknown } & Record<string, unknown>, 
    OutputObj = { [Key in T]?: InputObj[Key] }
>(inputObject: InputObj, keysToInclude: T[]): OutputObj {
    let result: OutputObj = {} as OutputObj;
    keysToInclude.forEach((key: T) => {
        if (Object.prototype.hasOwnProperty.call(inputObject, key)) {
            Object.assign(result, { [key]: inputObject[key] });
        }
    });
    return result;
}

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

Display a React functional component

Greetings, friends! I recently created a React app using functional components and now I am looking to print a specific page within the app. Each page is its own functional component, so I was wondering if it's possible to print a component individual ...

Error encountered when attempting to utilize Path Aliases in Angular 11.tsconfig

Currently, I am working on a project using Angular 11 and aiming to utilize short imports like import {smthg} from '@common' instead of import {smthg} from '../../../common' However, I keep encountering errors in IDEA: TS2307: Cannot f ...

Error encountered in Angular2: Attempted to access property 'compilerOptions' which is undefined

I encountered a TypeError: Unable to access the 'compilerOptions' property of undefined Below is the snippet of my compilerOptions code: { "compilerOptions": { "target": "ES5", "module": "commonjs", "emitDecoratorMetadata": tr ...

Using a class as an interface in TypeScript is a common practice when a constructor is

Consider a scenario where I have a class structured like this: class MyClass { a: string } Now, let's say I create a variable with the following definition: let obj: MyClass = { a: 2 } An error will be triggered in Typescript because 2 is not ...

Utilizing nested namespaces for optimal organization and clarity

Is it possible to export a namespace A with another namespace B nested within it? For example: // b.ts export namespace B { export const val = 'val'; } // a.ts export namespace A { //... some thing import B as namespace } --- the above wil ...

Strategies for redirecting search queries when adding a new path

Issue I am facing a challenge with pushing a new path to the URI while maintaining existing search queries. For example: Current URL: https://example.com/foo?bar=123&foobar=123 When I use history.push('newPath'), I end up with https://exa ...

Ensuring Koa ctx.query is valid prior to invoking the handler function

I'm currently working on a basic route that looks like this: router.get('/twitter/tweets', async (ctx) => { const { limit, page, search } = ctx.query ctx.body = { tweets: await twitter.all(limit, page, search), } }) The issue I ...

What are the reasons behind the unforeseen outcomes when transferring cookie logic into a function?

While working on my express route for login, I decided to use jwt for authentication and moved the logic into a separate domain by placing it in a function and adjusting my code. However, I encountered an issue where the client side code was unable to read ...

Can someone explain the distinction between 'return item' and 'return true' when it comes to JavaScript array methods?

Forgive me for any errors in my query, as I am not very experienced in asking questions. I have encountered the following two scenarios :- const comment = comments.find(function (comment) { if (comment.id === 823423) { return t ...

Oops! Angular2 couldn't find a provider for HttpHandler

I have been working on implementing HttpCache through an interceptor. Below is the code snippet for caching-interceptor.service.ts: import { HttpRequest, HttpResponse, HttpInterceptor, HttpHandler, HttpEvent } from '@angular/common/http' import ...

The parameter 'data' is assumed to have an 'any' type in React hooks, according to ts(7006)

It's perplexing to me how the 7006 error underlines "data," while in the test environment on the main page of React Hooks (https://react-hook-form.com/get-started#Quickstart), everything works perfectly. I'm wondering if I need to include anothe ...

Exploring NestJs: The Importance of DTOs and Entities

In my project, I'm currently experimenting with utilizing DTOs and Entities in a clever manner. However, I find it more challenging than expected as I develop a backend system for inventory management using NestJs and TypeOrm. When my client sends me ...

Import Information into Popup Window

When a user clicks on the "view" button, only the details of the corresponding challenge should be displayed: Currently, clicking on the "view" button loads all the challenges. This is because in my view-one-challenge.component.html, I have coded it as fo ...

Leveraging NPM workspaces in combination with Expo and Typescript

I'm struggling to incorporate NPM 7 workspaces into a Typescript Expo project. The goal is to maintain the standard Expo structure, with the root App.tsx file, while segregating certain code sections into workspaces. I'm facing challenges compil ...

Enhance a subject's behavior by overriding the .next method using a decorator

Currently, I am working on an Angular application where I have numerous Subjects, BehaviorSubjects, and ReplaySubjects as properties in various services. I am attempting to create a TypeScript decorator that can be added to some of these Subjects to enhanc ...

What is the best way to refresh my component following a delete operation in React?

I am currently facing an issue with using Sweetalert2 and React (tsx) where I am unsure how to refresh my item list after deleting methods. Below is the code snippet that I have for a button that implements these functions: function DeleteCard(item: DataI ...

An array of objects in Typescript utilizing a generic type with an enum

Here’s a glimpse of code that showcases the issue: enum ServicePlugin { Plugin1, Plugin2, Plugin3, } interface PluginOptions { [ServicePlugin.Plugin1]: { option1: string }; [ServicePlugin.Plugin2]: { option1: number; option2: number }; } type ...

Issue with Displaying Local Server Image in Angular 2 HTML

I am facing an issue with my Angular 2 Application. It retrieves items from a local database where the server stores the image of the item and the database stores the path to that image stored on the server. While I can retrieve all the items without any p ...

In a situation where Typescript fails to provide enforcement, how can you effectively indicate that a function is not defined for specific value(s)?

If I were to utilize Typescript to create a function called mean that calculates the mean of an array of numbers, how should I handle the scenario where the array is empty? Enforcing that an array must be non-empty can be inconvenient, so what would be th ...

Extending Record in Typescript: A Comprehensive Guide

When working on interfaces, I often find myself wanting to extend the type Record in order to define objects with predefined keys and optional values without knowing their names. For instance: interface Person extends Record<string, string>{ phonen ...