How do you type a function in TypeScript that accepts an object with properties of any other type, including none at all?

My preference in animals

type Animal = {
  name: string;
  age: number;
  dimensions: number[];
};

Now I aim to create a function that allows me to input an object with any combination of those fields, but strictly only those fields and with the correct type. For example

type OnlyAnimalProps = Record<string, any>;  // not recommended

function createAnimal(parent: Animal, props: OnlyAnimalProps) {
   return {...parent, ...props};
}

These examples should work fine

g1 = createAnimal(someAnimal, {});  // okay
g2 = createAnimal(someAnimal, {name: "Cindy"});  // okay
g3 = createAnimal(someAnimal, {age: 12, dimensions: [1, 3, 2]});  // okay

However, these examples should not work

e1 = createAnimal(someAnimal, {height: 123});  // wrong, "height" property doesn't exist
e2 = createAnimal(someAnimal, {name: 456});  // wrong, name should be a string

Playground

I understand this solution may already exist, but my searches have not yielded results

Answer №1

To easily achieve this, you can utilize the Partial<T> utility type that transforms an object type T by making all properties optional. This can be represented as:

type PartialAnimal = Partial<Animal>;
/* type PartialAnimal = {
    name?: string;
    age?: number;
    dimensions?: number[];
} */

You can then apply Partial<Animal> to define the props type in your code:

function createAnimal(parent: Animal, props: Partial<Animal>) {
  return { ...parent, ...props };
}

This approach works well for the examples you have provided:

const someAnimal = { name: "Bob", age: 11, dimensions: [4, 2, 1] };

const g1 = createAnimal(someAnimal, {});  // ok
const g2 = createAnimal(someAnimal, { name: "Cindy" });  // ok
const g3 = createAnimal(someAnimal, { age: 12, dimensions: [1, 3, 2] });  // ok

const e1 = createAnimal(someAnimal, { height: 123 }); // error
const e2 = createAnimal(someAnimal, { name: 456 });  // error

For a hands-on demonstration of this concept, you can check out the code on the TypeScript playground via this 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

Using formControlName with an Ionic2 checkbox allows for seamless integration of

Currently facing an obstacle with checkboxes in ionic2. Here is how I am using the checkbox: <ion-item> <ion-label>Agree</ion-label> <ion-checkbox color="dark" id="agree" name='agree' class="form-control" formContro ...

Why am I encountering issues accessing a child property in TypeScript?

Here is some TypeScript code that I am working with: export interface SelectQuery_thing { __typename: "ThingQueryPayload"; content: (SelectQuery_thing_content | null)[]; pageInfo: SelectQuery_thing_pageInfo; } export interface SelectQuery_thing_con ...

Is it possible to create an observable with RXJS that emits only when the number of items currently emitted by the source observables matches?

I am dealing with two observables, obs1 and obs2, that continuously emit items without completing. I anticipate that both of them will emit the same number of items over time, but I cannot predict which one will emit first. I am in need of an observable th ...

inject a dynamic loading icon within the choices of a datalist in an Angular application

<input list="dataUsers" formControlName="user" placeholder="Type the user name" class="form-control form-control-lg" type="text" (ngModelChange)="doSearch($event)"/> <datalist id=&q ...

Investigating SCSS Issues: The Problem with Absolute Imports

I am working on a project with the following structure: - my/project - assets - images - image-name.svg - source - components - MyComponent - MyComponent.module.scss - ... - ... ...

Retrieve the runtime configuration object or file using Jest

Is there a way to access the Jest runtime config object or file path? I wanted to utilize runtime config properties in my custom matchers. // ./jest.config.js const path = require("path"); module.exports = { prop1: "foo", prop2: "bar" }; // my-custo ...

The timestamps I generate are based on the day following the date

While creating a schema and using {timestamps:true} in Mongo, the fields 'createdAt' and 'updateAt' are supposed to be automatically generated. However, I have noticed that when creating a document with this setup, the day of the date i ...

Response type tailored to specific input type

I am working on defining types for a simple function called fun. Below are the interfaces for the input and response: interface Input { test1?: true test2?: true test3?: true } interface Res { test1?: string test2?: string test3?: string } N ...

TypeORM does not have the capability to effectively remove a row when there is a ManyToOne or

I'm currently grappling with a problem that has me stumped. I've spent countless hours trying to find a solution, but to no avail. I'm using MS-SQL on Azure. The structure of my entities is as follows: Customer and Visits: OneToMany (Prima ...

Guide on toggling the button by clicking on the icon to turn it on or off

Within my angular application, I have implemented font icons alongside a toggle switch. Initially, the switch is in the ON state. The specific functionality desired is for clicking on an icon to change its color from white to red (this has been achieved) ...

Steps for personalizing the dataset on a PrimeNG bar graph

I'm currently working with primeng in an Angular project and I need to create a bar chart where the last two horizontal bars have different colors. Right now, the last two bars are incorrectly being assigned to represent dogs and cats. My goal is to ...

Enforce Immutable Return in TypeScript

Hello, I am curious to know if there is a way to prevent overwriting a type so that it remains immutable at compile time. For example, let's create an interface: interface freeze{ frozen: boolean; } Now, let's define a deep freeze function: f ...

Here's a method to extract dates from today to the next 15 days and exclude weekends -Saturday and Sunday

Is there a way to generate an array of dates starting from today and spanning the next 15 days, excluding Saturdays and Sundays? For example, if today is 4/5/22, the desired array would look like ['4/5/22', '5/5/22', '6/5/22' ...

What is the functionality of input onChange in React when using state management?

Whenever I try to log the value of the input after each onChange event, there seems to be an odd one event delay. For example, if 'some text' is the default input value and I remove the letter 't' by pressing backspace/delete, it first ...

Expanding the capabilities of Hapi types in Typescript

I'm in the process of enhancing existing hapi definitions by incorporating a new type, specifically the seneca type. Here's an example: interface SenecaMethods { act: any; add: any; } interface HapiServer extends Hapi.Server { info: ...

Adding client-side scripts to a web page in a Node.js environment

Currently, I am embarking on a project involving ts, node, and express. My primary query is whether there exists a method to incorporate typescript files into HTML/ejs that can be executed on the client side (allowing access to document e.t.c., similar to ...

What is the best way to fetch the id of the option that has been chosen from a bootstrap drop-down menu?

I recently created a basic drop-down list like this: https://i.sstatic.net/4Tlxx.png Here is the HTML code for it: <select class="form-control" id='0' (change)="retrieveValue($event.target)"> <option id='0'>{{ g ...

Using a loop variable within a callback function in JavaScript/TypeScript: Tips and tricks

I have a method in my TypeScript file that looks like this: getInitialBatches() { var i = 0; for (var dto of this.transferDTO.stockMovesDTOs) { i++; this.queryResourceService .getBatchIdUsingGET(this.batchParams) ...

What is the best way to declare a global TypeScript variable in a definition file to make it accessible for import?

My issue revolves around an external JS library that contains a global parameter: function Thing() { ... } ... var thing = new Thing(); I have a TypeScript definition file named thing.d.ts with the following content: declare var thing: ThingStatic; ex ...

MaterialUI Divider is designed to dynamically adjust based on the screen size. It appears horizontally on small screens and vertically on

I am currently using a MaterialUI divider that is set to be vertical on md and large screens. However, I want it to switch to being horizontal on xs and sm screens: <Divider orientation="vertical" variant="middle" flexItem /> I h ...