TypeScript - Minimize redundancy when defining types for a class and its constructor arguments

Here is a class structure I am currently using:

class Person {
    id?: string = uuid();
    name: string;

    constructor(data: Person) {
        _.merge(this, data);
    }
}

The 'uuid' function generates an id and '_' refers to lodash.

I am facing an issue where I have a function that requires the id parameter:

function savePersonInDb(p: Person & { id: string }) {...}
However, TypeScript does not allow calling it with a new Person() instance because id is optional, even though it is always instantiated when calling the constructor.

I am aware that I could modify my class like this:

interface PersonData {
    id?: string;
    name: string;
}

class Person {
    id: string = uuid();
    name: string;

    constructor(data: PersonData) {
        _.merge(this, data);
    }
}

However, I am reluctant to rewrite all the attributes twice. Is there a more straightforward way to achieve what I need?

In my actual project, I have numerous attributes, so it would be great if I could avoid duplicating them for every class.

Thank you for your assistance!

Answer №1

If you want to create a type in TypeScript that excludes a specific property, such as 'id', you can use the Omit utility type. This will allow you to define a new type based on an existing type but without including the specified property. You can try it out in this TypeScript playground:

type OptionalId<T> = {
    id?: string
} & Omit<T, 'id'>

// PersonData is automatically updated when Person is changed
type PersonData = OptionalId<Person>;

// savePersonInDb just takes Person
function savePersonInDb(person: Person) {}

class Person {
    id: string = ''; // uuid();
    name: string = '';
    member1: number = 0;
    // member2 and so on

    constructor(data: PersonData) {
        // _.merge(this, data);
    }
}

// id is optional
const person = new Person({
    name: 'test',
    member1: 5
});

// new person object can be used.
savePersonInDb(person)

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

Modifying the response header in a node.js middleware: A step-by-step guide

I've been researching this question extensively on Google, but unfortunately, none of the solutions seem to work for me. The issue I'm facing is related to adding a specific property to the response header called "isAuth," which needs to be set ...

Issue with type narrowing and `Extract` helper unexpectedly causing type error in a generic type interaction

I can't seem to figure out the issue at hand. There is a straightforward tagged union in my code: type MyUnion = | { tag: "Foo"; field: string; } | { tag: "Bar"; } | null; Now, there's this generic function tha ...

Could you please clarify the type of event on the onInputChange props?

I am encountering an issue with using React.ChangeEvent on the mui v4 autocomplete component as I prefer not to use any other method. However, I keep getting an error indicating that the current event is incompatible. const handle = (e: React.ChangeEv ...

Eslint for Typescript in Vue is throwing an error with a message "Unexpected token, expecting ','. Make sure to

Whenever I attempted to utilize vue's type assertion, I kept encountering this eslint error. To illustrate, consider the following snippet: data: function () { return { sellerIdToListings: {} as any, // 'as' Unexpected to ...

Bovine without Redis to oversee queue operations

Can Bull (used for job management) be implemented without utilizing Redis? Here is a segment of my code: @Injectable() export class MailService { private queue: Bull.Queue; private readonly queueName = 'mail'; constructor() { ...

Utilizing Typescript and Jest to prevent type errors in mocked functions

When looking to simulate external modules with Jest, the jest.mock() method can be utilized to automatically mock functions within a module. After this, we have the ability to modify and analyze the mocked functions on our simulated module as needed. As ...

Tips on streamlining two similar TypeScript interfaces with distinct key names

Presented here are two different formats for the same interface: a JSON format with keys separated by low dash, and a JavaScript camelCase format: JSON format: interface MyJsonInterface { key_one: string; key_two: number; } interface MyInterface { ...

A guide to integrating a component into another component in Angular

Currently, I am encountering an issue with importing a component into another in my Ionic 5.0.0 application. Within my application, I have two separate modules: ChatPageModule and HomePageModule. My objective is to include the Chat template within the Hom ...

JavaScript's Array.map function failing to return a value

Here is a snippet of code from an api endpoint in nextJS that retrieves the corresponding authors for a given array of posts. Each post in the array contains an "authorId" key. The initial approach did not yield the expected results: const users = posts.ma ...

I encountered an error stating "Buffer is not defined" originating from the Deode/Encode Stream Bundle.js script, not from my own code

I've encountered a major issue while attempting to update my npm project to webpack 5, and now I'm left with just one persistent error: bundle.js:1088566 Uncaught ReferenceError: Buffer is not defined at bundle.js:1044980:24 ...

Angular2 ERROR: Unhandled Promise Rejection: Cannot find a matching route:

I'm facing an issue with my Angular2 application while utilizing the router.navigateByUrl method. Within my component, there is a function named goToRoute, structured as follows: router.goToRoute(route:string, event?:Event):void { if (event) ...

Angular seems to be experiencing issues with maintaining context when executing a function reference for a base class method

Imagine we have CtrlOne that extends CtrlTwo, with a componentOne instantiated in the template of CtrlOne. Here is some code to illustrate the issue: class CtrlOne extends CtrlTwo { constructor() { super(); } } class CtrlTwo { sayMyName(name: st ...

How to create a collapse feature that allows only one item to be open at a time in Angular

I developed an angular app with a collapse feature, but I noticed that multiple collapses can be open at once. I am utilizing Ng-Bootstrap collapse for this functionality. Below is the code snippet from the TS file: public isCollapsed = true; And here is ...

Creating a dynamic list in Typescript from a tuple array without any intersections

const colors = ["red", "blue", "green", "yellow"] as const; const buttonSizes = ["small", "medium", "large"] as const; type ColorType = (typeof colors)[number]; type SizeType = (typeof b ...

What prevents `console.log` from working within a button click event?

Why is this not functioning correctly? <button (click)="console.log('ok');">Display Details</button> The error message reads: Cannot read property 'log' of undefined However, a console.log statement in the class construc ...

Understanding and processing HTML strings in typescript

I am currently utilizing TypeScript. Within my code, there is an object named "Reason" where all variables are defined as strings: value, display, dataType, and label. Reason = { value: '<ul><li>list item 1</li><li&g ...

Is there a way to verify an if-else statement in the ngStyle background property with Angular 7?

I have a collection of cards that need to be shown in a component. Each card contains a cover-image with an URL fetched from the server. In my component.html, I am using ngFor as follows: <div [style.background-image]="'url('+row.companyId?.c ...

explore and view all images within a directory

Hello, I am new to NextJS and encountering some issues. I have a folder in my public directory containing 30 images that I want to import all at once in the simplest way possible, without having to import each image individually by name. Here is the curren ...

Error TS2315: Invalid Type Assignment for Angular 6 ModuleWithProviders

Hey there, I'm encountering an issue that's got me scratching my head. I've shared some of my code in the hopes that it might shed some light on the problem. The problem cropped up as soon as I started working on a Reactive Form. Let me s ...

Loop through a collection of elements of a certain kind and selectively transfer only certain items to a different collection of a different kind

When working with typescript, I am faced with the challenge of dealing with two arrays: interface IFirst{ name: string; age: number } interface ISecond { nickName: string; lastName: string; } myFirstArray: IFirst[]; mySecondArray: ISe ...