Varied Data Transfer Objects used for requests and responses

Currently, I am dealing with MongoDB and subdocuments. MongoDB automatically adds extra fields that cannot be specified in a POST request; they can only be retrieved using a GET request. To put it simply: different data transfer objects (dtos).

I am utilizing Swagger and OpenAPI to automatically generate API documentation and I want to avoid redundancy by reusing the same definitions multiple times.

Initially, I considered using extend:

export class CreateSingleAttributeRequestDto {
  @ApiProperty({
    example: 10,
    description: 'Attribute Value',
    format: 'integer',
  })
  @IsInt()
  readonly value: number = SINGLE_ATTRIBUTE_VALUE_DEFAULT;
}

export class FetchSingleAttributeResponseDto extends CreateSingleAttributeRequestDto {
  @ApiProperty({
    example: 30,
    description: 'GENERATED. Cost of the attribute.',
    format: 'integer',
  })
  @IsInt()
  readonly ap?: number;
}

export class CreateAttributeRequestDto {
  readonly attributes?: {
    readonly cou?: CreateSingleAttributeRequestDto;
    readonly sgc?: CreateSingleAttributeRequestDto;
  }
}

export class FetchAttributeResponseDto extends CreateAttributeRequestDto {
  @ApiProperty({
    example: 98,
    description: 'GENERATED. Sum of all values of the 8 attributes',
    format: 'integer',
  })
  @IsInt()
  readonly total?: number;
}

(For clarification purposes: this code pertains to an RPG character creator. Points are utilized to purchase attributes, and for compatibility with other functionalities, costs are auto-generated upon document creation.)

The issue here lies in the fact that

FetchAttributeResponseDto extends CreateAttributeRequestDto
- which does not include the extra fields defined in FetchSingleAttributeResponseDto

My inclination would be to - instead of extending CreateAttributeRequestDto - "copy" it - and use

 readonly cou?: FetchSingleAttributeResponseDto
instead

However, this approach goes against the dry principle and just doesn't feel right. Is there a more optimal solution?

Additionally, the created MongoDB Document has supplementary fields like _id, __v, createdAt, updatedAt - since I don't wish to specify these four keys each time, I contemplated creating another class for them that could be extended - unfortunately, as far as I know, TypeScript does not support multiple inheritance. How would you tackle this issue?

Answer №1

If you're looking to accomplish this, consider utilizing @nestjs/mapped-type. You can choose from options like OmitType, PickType, or PartialType when extending as shown below:

export class UpdateUserInput extends PartialType(CreateUserInput) {}

To learn more, check out the official blogpost.

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

Tips for validating that a TypeScript parameter is a union with a specific type

Is there a way to create a TypeScript function that confirms an argument is a union type containing another, more specific union? Here's an example scenario: type Command = { name: string [key: string]: any } type Insert = { name: 'insert ...

(TS 2556) I'm puzzled as to why a type error is being thrown for a spread argument that was clearly defined and passed as a rest parameter

function debouncePromise<TParams extends Array<unknown>, TRes>( fn: (a: TParams) => Promise<TRes>, time: number, ) { let timerId: ReturnType<typeof setTimeout> | undefined = undefined; return function debounced(...args: TP ...

Ensure that the JSON file containing translations is fully loaded prior to proceeding with the loading of the Angular application

In our Angular application, we have integrated internationalization using ng2-translate. We are utilizing the .instant(...) method for translations to simplify the process without having to subscribe to observables. One issue we are facing is that using . ...

Learn how to open a component in a new browser tab using Angular from a different component

I wish to display the MapComponent in a new browser tab when a button in my AppComponent html file is clicked. Currently, when I click the button, the MapComponent opens in a new tab but it also displays the button. How can I configure it so that only the ...

Issue: Module 'stylelint' not found in Angular Project

I've been attempting to execute this command to validate all of the .scss files (and even tried with .css files) and I keep encountering this error. $ stylelint "apps/**/*.scss" It worked once before but not anymore, even after restarting my compute ...

What is the method for defining a mandatory incoming property in an Angular2 component?

In my current project, I am developing a shared grid component using Angular2 that requires an id property. export class GridComponent { @Input() public id: string; } I'm looking for a way to make the id property mandatory. Can you help me with ...

Error encountered: The property 'localStorage' is not found on the 'Global' type

Calling all Typescript enthusiasts! I need help with this code snippet: import * as appSettings from 'application-settings'; try { // shim the 'localStorage' API with application settings module global.localStorage = { ...

Finding the solution to the perplexing issue with Generic in TypeScript

I recently encountered a TypeScript function that utilizes Generics. function task<T>(builder: (props: { propsA: number }, option: T) => void) { return { run: (option: T) => {}, } } However, when I actually use this function, the Gener ...

Unable to narrow down the truthiness within nested functions: TypeScript issue

When analyzing the code in the shared playground (Playground Link), the compiler is showing an error indicating that Object is possibly 'null'. Could there be any scenario where the refresh function could be called, leading to a situation where ...

Animation of lava effect in Angular 7

I have a unique Angular 7 application featuring a homepage with a prominent colored block at the top, along with a header and various images. My goal is to incorporate lava effect animations into the background similar to this CodePen example. If the link ...

Tips on how to retrieve an Observable Array instead of a subscription?

Is there a way to modify this forkJoin function so that it returns an observable array instead of a subscription? connect(): Observable<any[]> { this.userId = this.authService.userId; this.habits$ = this.habitService.fetchAllById(this.userId); this.s ...

``Are you experiencing trouble with form fields not being marked as dirty when submitting? This issue can be solved with React-H

Hey there, team! Our usual practice is to validate the input when a user touches it and display an error message. However, when the user clicks submit, all fields should be marked as dirty and any error messages should be visible. Unfortunately, this isn&a ...

Should mutators be encapsulated within a class contained in a JS Module for better code organization and maintainability?

In order to maximize functionality of our new product using JavaScript, we have implemented an Authentication module that manages a tokenPromise which is updated upon user logins or token refreshes. It seems imperative to allow for mutation in this process ...

Prevent clicking outside the bootstrap modal in Angular 4 from closing the modal

Just starting out with angular4 and incorporating bootstrap modal into my project. I want the modal to close when clicking outside of it. Here's the code snippet: //in html <div bsModal #noticeModal="bs-modal" class="modal fade" tabindex="-1" rol ...

I'm interested in learning how to implement dynamic routes in Nexy.js using TypeScript. How can I

I have a folder structure set up like this: https://i.stack.imgur.com/qhnaP.png [postId].ts import { useRouter } from 'next/router' const Post = () => { const router = useRouter() const { pid } = router.query return <p>Post: {p ...

Utilizing Angular and TypeScript: The best approach for managing this situation

I need some guidance on handling asynchronous calls in Angular. Currently, I am invoking two methods from a service in a controller to fetch an object called "categoryInfo." How can I ensure that these methods return the categoryInfo correctly and displa ...

Exploring Immediately Invoked Function Expressions in TypeScript

I came across an interesting article on self-invoking functions in JavaScript by Minko Gechev. This article teaches us how to create a JavaScript function that calls itself immediately after being initialized. I am curious about how we can achieve this in ...

Creating a WebExtension using Angular and TypeScript

I am currently working on creating a WebExtension using Angular and Ionic. The extension successfully loads the application and enables communication between Content Script and Background Script. However, I am facing an issue where the TypeScript code is n ...

An issue occurred while trying to use a function that has a return type of NextPage

After successfully implementing the code below: const HomePage: NextPage = () => ( <div> <div>HomePage</div> </div> ); I wanted to adhere to Airbnb's style guide, which required using a named function. This led me t ...

Tips for displaying or concealing a div using Angular Js

I have set up two div elements with a dropdown control in one named div1. I am looking to hide div2 until a value is selected in the dropdown. How can I show or hide a div based on ng-change, ensuring that div2 remains hidden until a value is selected? Cod ...