A guide on merging decorated parameters to form a unified object in TypeScript

I'm currently working on a NestJS controller with multiple methods that have a similar structure, like the example below:

@Post(':id/something')
async doSomething(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() body: SomethingDto,
    @AuthUser() updater: IAuthUser,
    @UploadedFiles() attachments: File[],
) {

    // Each method performs a distinct operation and uses a different DTO type,
    // but the parameters remain consistent.
}

In this scenario, Param and Body are from @nestjs/common, AuthUser is a custom decorator, and UploadedFiles is from @nestjs/multer.

I am wondering if there is a way to streamline this by creating a unified parameter decorator that can be implemented for a parameter object.

@Post(':id/something')
async doSomething(@SomeDecorator(SomethingDto) params: Params<SomethingDto>) {
    // Ideal solution would allow me to destructure params like this
    const { id, body, user, attachments } = params;
}

I've come across techniques involving class and property decorators, but nothing applicable to parameter decorators has been found so far.

Answer №1

Unfortunately, that option is not currently available.

NestJS operates by injecting values when needed through an internal dependency injection system. In order for this process to work correctly, it must know which values to inject from the start. Without explicitly defining these values, the injection won't occur, as you can't create something out of nothing.

A potential workaround could be to manually inject raw req and res objects using the @Req() and @Res() decorators, but it may be more practical to consider creating a middleware at this stage.

If you're feeling adventurous, delve into the inner workings of NestJS's DI mechanism (which may utilize a third-party package) to understand how it manages value injections for these parameters. This exploration could offer valuable insights.

Answer №2

Technically speaking, there is a possibility to create a single mega decorator that combines all these functionalities into a custom parameter decorator. However, I strongly advise against this approach. It will result in a complex and hard-to-maintain decorator with minimal validation capabilities. Additionally, it would necessitate the use of intricate DTOs for functionality.

In the event that you still wish to proceed with this method, the implementation will look something like this:

export const SomeMegaDecorator = createParamDecorator((data: unknown, ctx: ExecutionContext) => {
  const req = ctx.switchToHttp().getRequest();
  return {
    params: req.params,
    user: req.user,
    body: req.body,
    files: req.files,
    file: req.file,
    query: req.query
  }
});

You would utilize it as follows:

@SomeMegaDecorator() { params, user, body, files, file, query }: SomeReallyUglyDto

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

Render JSON value as an input in an Angular component using @Input()

In my app.component.html file, I have included the following template: <test [someInput]="data"></test> The 'data' variable is a JSON object property structured like this: let data = {hello: "ciao"} Below is the code from my test. ...

Utilizing asynchronous methods within setup() in @vue-composition

<script lang="ts"> import { createComponent } from "@vue/composition-api"; import { SplashPage } from "../../lib/vue-viewmodels"; export default createComponent({ async setup(props, context) { await SplashPage.init(2000, context.root.$router, ...

Encountering issues with accessing properties of undefined while chaining methods

When comparing lists using an extension method that calls a comparer, I encountered an error. Here is the code snippet: type HasDiff<T> = (object: T, row: any) => boolean; export const isListEqualToRows = <T>(objects: T[], rows: any[], has ...

Creating custom observables by utilizing ViewChildren event and void functions in Angular 12: A step-by-step guide

I am currently working on developing a typeahead feature that triggers a service call on keyup event as the user types in an input field. The challenge I face is that my input field is enclosed within an *ngIf block, which requires me to utilize ViewChildr ...

Transmit data from a child component to a Vue JS page through props, and trigger the @blur/@focus function to access the prop from the parent component

Seeking guidance on working with props in Vue JS. As a newcomer to Vue, I hope that my question is clear. I've included my code snippet below, but it isn't functioning correctly due to missing Vue files. In my attempt to use a prop created in t ...

"Error encountered: 'Callable function cannot be invoked on Mongoose model

In my Nest JS service, the code structure is as follows: import { Injectable } from '@nestjs/common'; import { Model } from 'mongoose'; import { InjectModel } from '@nestjs/mongoose'; import { Collection } from './inter ...

Create a TypeScript function that returns a string or undefined without any arguments

I have come across this TypeScript function: get_value(): T | undefined { let TValue: T | undefined; return TValue; } get_value() // result => undefined The return type can be either "T" or "undefined", which means the function always returns ...

Angular 4 file upload verification: Ensuring safe and secure uploads

Is there a recommended method to validate the file type when uploading a file in an Angular 4 form? Are there any simple ways to accomplish this task? ...

The 'createGame$' property is not found on the 'GameService' object

A new GameService has been crafted with the implementation of the ServiceInterface: export interface ServiceInterface { emitter$; actions: any[]; [action: string]: any; } export class GameService implements ServiceInterface { constructor() { ...

Receiving feedback from an http.post request and transferring it to the component.ts file in an Angular

Currently, I am facing an issue with passing the response from an http.post call in my TypeScript service component to an Angular 2 component for display on the frontend. Below are the code structures of my service.ts and component.ts: getSearchProfileRes ...

Is it possible to verify a file's type with Nestjs Pipes and the FileTypeValidator?

I am facing an issue with implementing a Nestjs route in a controller that includes a file upload using Multer. The goal is to edit a user's profile picture, so I need to validate that the uploaded file is an image. However, despite using the FileType ...

Troubleshooting: Angular input binding issue with updating

I am currently facing a challenge with connecting a list to an input object in Angular. I was expecting the updated values to reflect in the child component every time I make changes to the list, but strangely, the initial values remain unchanged on the sc ...

Angular error: Unable to assign value to 'Data' property as it is undefined

Within my code, I am invoking this operation in the ngOnInit function to ensure that previously edited data can be viewed when the page is reopened. The property StickerData belongs to the interface IStickerData. However, I keep encountering an error: ERRO ...

When trying to convert JavaScript to TypeScript, an error occurs stating that the module cannot

Currently in the process of migrating my project from JavaScript to TypeScript, focusing on the server-side implementation. Encountering an error which is detailed below. internal/modules/cjs/loader.js:883 throw err; ^ Error: Cannot find module &apos ...

How can I retrieve a certain type of object property in TypeScript?

Imagine having a collection of flags stored in an object like the example below: type Flags = { flag1: string, flag2: string, flag3: boolean, flag4: number } // const myFlags: Flags = { // flag1: 'value 1', // flag2: 'value 1&ap ...

Ways to activate a click event using typescript

Having trouble getting the click event to trigger in TypeScript. I have a table with a div inside it. Initially, the table data is not loading correctly. However, manually clicking on the table refreshes the data. How can I programmatically trigger the cli ...

Failure to trigger the callback for mongoose.connection.once('open') event

Currently, I am in the process of setting up a custom Node server using Next.js. Although I'm utilizing Next.js this time around, it should not affect the outcome. In my previous applications, I always relied on mongoose.connection.once('open&ap ...

Is the Cyrillic encoding feature not functioning properly in Angular 4 with .Net Core 2?

Struggling with handling Cyrillic characters in my current project. Utilizing .Net Core 2 along with Angular 4.2.5 I've noticed that displaying a string in the templates using {{ someCyrillicString }} works fine. However, encountering issues when tryi ...

When attempting to use a context, the type '...' cannot be assigned to type '...'

In my Next.js project, I am utilizing createContext to implement a dark mode button. The original jsx file for this functionality is called ThemeContext.tsx, and I am currently in the process of converting it to TypeScript. "use client"; import ...

Solving the issue of refreshing HTML Canvas drawings in Vue3 using the Composition API

In my typescript code base, I have successfully created a Sudoku board by directly manipulating the DOM and utilizing an HTML Canvas element with its API. Now, I am looking to elevate my project to a full website and integrate what I have into a Vue3 proj ...