Type that is a generic object derived from the keyof keyword

I am trying to create a generic function that will only update values of type object within a map, and ignore anything else.

Is it possible to achieve this? I have looked for a solution but haven't found one yet.

enum SKey {
  key1 = "key1",
  key2 = "key2",
}

type SItem = {
  [SKey.key1]: boolean;
  [SKey.key2]: {
    attr1: string;
    attr2: boolean;
  };
};

const mapDB: SItem = {
  [SKey.key1]: true,
  [SKey.key2]: {
    attr1: "hello",
    attr2: true,
  },
};

export function updateDbItem<K extends keyof SItem>(
  key: K,
  newFields: Partial<SItem[K]>
) {
  const item: SItem[K] = mapDB[key];
  mapDB[key] = { ...item, ...newFields };
}

However, I am encountering the following error:

error TS2698: Spread types may only be created from object types.

mapDB[key] = { ...item, ...newFields };
              ~~~~~~~~

Would appreciate any help or suggestions on how to resolve this issue. Thank you!

Answer №1

To create a union of keys with object-type values, you can utilize a mapped type.

In the provided code snippet, only SKey.key2 is included based on the current entries in SItem. Adding more entries to SItem would result in additional keys meeting the criteria being included.

Here is an example:

TS Playground

type SItemObjectKey = keyof {
  [
    K in keyof SItem as SItem[K] extends Record<string, unknown>
      ? K
      : never
  ]: unknown;
};

export function updateDbItem<K extends SItemObjectKey>(
  key: K,
  newFields: Partial<SItem[K]>
) {
  const item: SItem[K] = mapDB[key];
  mapDB[key] = { ...item, ...newFields }; // Ok now!
}

For reference, check out the utility type Record<Keys, Type>

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

Issues with naming in Gulp, Angular2 Final, and Visual Studio: "Cannot find name" and "Duplicate identifier" errors

Recently, I updated my project to utilize the final release of Angular 2 and also upgraded Visual Studio to use TypeScript 2.0.3 from the Tool -> Extensions and Updates manager. I compile my TypeScript using Gulp, and it compiles without any errors. Ho ...

Solution for retrieving the current method in Compact Framework 3.5 without using MethodBase.GetCurrentMethod()

I am looking to incorporate a Linq IQueryable Toolkit into my project on the .NET Compact Framework. Unfortunately, the Linq capabilities in CF are somewhat limited - specifically, the IQueryable interface is not available. As a result, I have turned to th ...

What could be the reason for the defaultCommandTimeout not functioning as expected in my script

Is there a way to wait for only one particular element in Cypress without having to add wait commands everywhere in the test framework? I've come across the solution of adding defaultCommandTimeout in the cypress.json file, but I don't want it t ...

The utilization of paths in tsconfig.json does not successfully resolve when working with Angular

I'm trying to set up Angular to understand paths in order to avoid using relative paths when importing files. However, despite my efforts, it doesn't seem to be working. Here is my code snippet: //tsconfig.app.json "compilerOptions":{ //lot ...

Creating a nested type using template literal syntax

Given a two-level nested type with specific properties: export type SomeNested = { someProp: { someChild: string someOtherChild: string } someOtherProp: { someMoreChildren: string whatever: string else: string } } I am looking ...

arranging a list in which the second characteristic might not be present

Looking for a solution to sort a table in an Angular project? The challenge is sorting by either a direct property of objects in the array or a child of that property. Take, for instance, sorting by associate.lastname versus associate.client.name. I'v ...

Absolute file path reference in Node.js

I'm working on a Node.js project using WebStorm IDE. Here's the structure of my project: The root folder is named "root" and inside are 2 folders: "main" and "typings". The "main" folder has a file called "foo.ts", while the "typings" folder co ...

Touched the Force of ngModel

I am looking to make the required fields show in red in the angular material when the "Submit" button is clicked. To achieve this, I need to trigger the input to be marked as touched. <div class="formRow"> ...

What is the best approach to retrieve all user information using React with TypeScript and the Redux Toolkit?

I'm currently using React with TypeScript and Redux Toolkit, but I've hit a roadblock trying to retrieve user information. Below is my userSlice.ts file: export const userSlice = createSlice({ name: "user", initialState: { user: null, } ...

Is there a way to automatically scroll 50 pixels down the page after pressing a button?

Is there a way to make my page scroll down in Angular when a button is clicked? I attempted to use this code, but it didn't have the desired effect. What is the best method for scrolling the page down by 50px? window.scrollBy(0, 50); ...

How to send a dynamic URL parameter to a function in Next.js TypeScript without using implicit typing

When utilizing the useRouter function with a parameter of type string, the following error is encountered: Type 'string | string[] | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type & ...

Is it possible to obtain a reference that can call an operator?

Is it possible to obtain a reference to an operator (like ===) in TypeScript? The reason behind this question is the following function: function dedup<T>(values: T[], equals: (a: T, b: T) => boolean): T[] { return values.reduce<T[]>((pre ...

The function's overloading is not compatible with its implementation

Currently, I am puzzled by the lack of functionality in some code that I am reviewing. The structure resembles this: function getValidity(x: "v1"): boolean; function getValidity(x: "v2"): { a: number; b: number }; function getValidity(x: any) { if (x == ...

Extracting data from an action using NgRx8

Hey everyone, I'm looking for some guidance on how to destructure action type and props in an ngrx effect. I'm struggling with this and could use some help! This is my list of actions: export const addTab = createAction( '[SuperUserTabs ...

Can we establish the set values for a function's parameter in advance?

I need to define the available values for a function's parameter in this way: let valueList = [ 'val1', 'val2', 'val3', ]; let getSomething = (parameter: valueList) => { // do something } I want the con ...

The error that has occurred is: `TypeError: The object on the right side of the 'instanceof' keyword is

Testing my function that verifies if a variable is an instance of a specific type and performs an action has been successful. I conduct the verification using the following code: myCheckingFunction = () => { if (target instanceof H.map.Marker) { ... ...

Guide on Importing All Functions from a Custom Javascript File

As a beginner in learning Angular, I am faced with the task of converting a template into Angular. However, I am struggling to find a solution for importing all functions from a custom js file into my .component.ts file at once. I have already attempted t ...

Is it possible to update the text within a button when hovering over it in Angular?

https://i.sstatic.net/ZhNeM.png https://i.sstatic.net/kb670.png I'm looking to update the text displayed inside a button when hovering over it, similar to the examples in these images. I have already implemented the active state, but now I just need ...

Building a Search Object using Template String Types

Here is a type definition that allows for specific responses: type Response = 'n_a' | 'n_o' | 'yes' | 'no' I want to create a type that ensures underscores are replaced with slashes: type ReplaceUnderscoreWithSlash& ...

The statement "import React from 'react'" is automatically removed by VS Code

When I need to remove unused modules that I no longer need, I frequently use shift + alt + o. This method has worked perfectly for me in the past when editing .tsx files. However, recently, VS Code seems to be removing the import React from 'react&ap ...