Abbreviation for ensuring type safety when combining properties from one object with another

Imagine we have an object x representing type X and an object y representing type Y.

Is there a way to combine (assign all properties) of y into x in such a way that if Y is not a proper subset of X, the compiler raises an error?

NOTE: While Object.assign(x, y) can technically achieve this, it won't raise an error if Y includes properties not found in X.

I am seeking a method similar to {...x} = y.

EDIT:

It's important to avoid reassignment to x since that would change the identity of x, which could be declared as const.

Answer №1

If you need a function that will raise an error if one type is not a subset of the other, you can use the following approach

// U is a subset of T
function merge<T extends U, U>(a:T, b:U):T{
  return {...a, ...b}
}

In case you want to overwrite 'a' with 'b', you can implement the function like this

function merge<T extends U, U>(a:T, b:U):T{
  for (const [key, value] of Object.entries(b)) {
    a[key as keyof U] = value
  }
  return a;
}

Here are some examples to demonstrate how this function operates

type A = {a:string, b:number, c:boolean}
type B = {a:number, b:number}
type C = {b:number, c:boolean}
type D = {a:string, d:string}

let a:A = {a:"Hi_a", b:1, c:true}
let b:B= {a:99, b:2}
let c:C = {b:3, c:false};
let d:D = {a:"Hi_d", d:"Low_d"}

let ab = merge(a,b) //compiler fail - Type B prop is incompatible
let ac = merge(a,c) //passes type C is a subset of type A
let ca = merge(c,a) //compiler fail - type A is a superset of type C
let ad = merge(a,d) // compiler fail - Type D has an extra property

Playground Link

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

Error encountered in Next.js: The function 'useLayoutEffect' was not successfully imported from 'react' (imported as 'React')

I've been in the process of migrating an application from CSR (using webpack only) to SSR, and I'm utilizing Next.js for this transition. Following the migration guide provided by Next.js for switching from vite (specifically focusing on parts r ...

Challenges with inferencing union types in TypeScript generics

type SingleOrArray<T> = T | [T] function f<T extends 'a' | 'b'>(a: SingleOrArray<T>, b: SingleOrArray<T>) { return a && b } f('a', ['b']) Then an error occurred: Argument of typ ...

What causes an interface to lose its characteristics when a property is defined using index signatures?

Here's the code snippet I'm having trouble with, which involves tRPC and Zod. import { initTRPC, inferRouterOutputs } from '@trpc/server'; import { z } from "zod"; const t = initTRPC.create(); const { router, procedure } = t; ...

Oops! The formGroup function in Angular 5 requires an instance of a FormGroup

While working with Angular 5, I encountered an error in this basic form. Here is the issue: Error Message: EditVisitanteDialogComponent.html:10 ERROR Error: formGroup expects a FormGroup instance. Please pass one in. Example: > > &l ...

Troubleshooting: Resolving the Error "Cannot find Property htmlFor on Custom React Component"

I am currently working with a custom component that looks like this: import React from "react"; import classnames from 'classnames'; import { ButtonVariantColor } from '../types/button'; export type IconButtonProps = { e ...

Issue: The code is throwing an error "TypeError: Cannot read property 'push' of undefined" in the JavaScript engine "Hermes

Can anyone assist me with filtering an array of objects in a TypeScript React Native project using state to store array values and filter objects in the array? Having trouble with the following error in the mentioned method: LOG after item LOG inside ...

Tailoring Aurelia for .cshtml integration

I stumbled upon an informative article detailing the integration of Razor partials (cshtml) with aurelia. Despite my efforts, I encountered difficulty in getting the code to execute properly and was informed by Rob Eisenberg's comment that Convention ...

Utilizing Next.js to create a Higher Order Component (HOC) for fetching data from a REST API using Typescript is proving to be a challenge, as the

In my withUser.tsx file, I have implemented a higher order component that wraps authenticated pages. This HOC ensures that only users with a specified user role have access to the intended pages. import axios, { AxiosError } from "axios"; import ...

What is the method for extracting date of birth data from .NET to Angular?

Struggling to fetch the date of birth from the database where it has been stored. After searching through multiple resources online, I am still unsure about how to accomplish this task. export class DetailsEmployeeComponent implements OnInit{ employeeD ...

AsExpression Removes Undefined from Type More Swiftly Than I Prefer

Utilizing an API that returns a base type, I employ the as keyword to convert the type into a union consisting of two sub-types of the original base type. interface base { a: number; } interface sub1 extends base { s1: number; } interface sub2 extends bas ...

Enhance existing functionalities in library with type augmentation strategy

I am interested in creating a library that includes a custom matcher function in TypeScript using Vitest. After following the documentation and adding a vitest.d.ts file with the necessary augmentations, everything appears to be working well. However, I ha ...

Testing the selection of dropdown values in Angular2 using unit tests

I have a dropdown menu for selecting countries. It defaults to a pre-selected value, and when the user changes it, they are redirected to the corresponding country page. However, I am facing an issue while trying to unit test the default value in the sele ...

Error: The identifier HTMLVideoElement has not been declared

Encountering an issue while attempting to build my Angular 9 Universal project for SSR: /Users/my-project/dist/server.js:28676 Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__metadata"])("design:type", HTMLVideoElement) ReferenceError: HTMLVideoElem ...

Performing bulk operations on all selected rows in a table using Angular 6

Within my Angular 6 web application, there is a table with checkboxes in each row. My goal is to be able to perform bulk actions on the selected rows, such as deleting them. One approach I considered was adding an isSelected boolean property to the data m ...

Enhance your coding experience with VScode's intellisense feature when working with TypeScript

declare type Item = { name: string; location: string; source: string; }; declare type CollectionOfItems = { [key: string]: Item; }; export const CollectionOfItems: CollectionOfItems = { ITEM_1: { name: 'Item 1', location: &ap ...

"Convert a date string to a date object using the verbose moment date

I utilized the materialize datepicker to select a date in French format. Now I need to convert this formatted date back to a date object for use in my API. Here's how I attempted to revert the date to a standard format: moment("dimanche 30 juillet 20 ...

What does the concept of "signaling intent" truly signify in relation to TypeScript's read-only properties?

Currently diving into the chapter on objects in the TypeScript Handbook. The handbook highlights the significance of managing expectations when using the readonly properties. Here's a key excerpt: It’s crucial to clarify what readonly truly signif ...

Troubleshooting connectivity issues between Entities in microORM and Next.js

While trying to run my Next.js application in typescript, I encountered the following error: Error - ReferenceError: Cannot access 'Member' before initialization After consulting the documentation at https://mikro-orm.io/docs/relationships#relat ...

What is the significance of `new?()` in TypeScript?

Here is a snippet of code I'm working with in the TypeScript playground: interface IFoo { new?(): string; } class Foo implements IFoo { new() { return 'sss'; } } I noticed that I have to include "?" in the interface met ...

What is the best way to iterate through an array of arrays using a foreach loop to calculate the total number of specific properties?

For instance, if YieldCalcValues were to look something like this: [ [ 850, 500 ], [ 3, 6 ], [ 1200, 5000 ], [ 526170, 526170 ] ] I am looking to create a foreach loop that calculates the yield per for each product. How can I accomplish this correctly? l ...