Differentiating Typescript will discard attributes that do not adhere to an Interface

Currently, I am working with an API controller that requires a body parameter as shown below:

insertUser(@Body() user: IUser) {}

The problem I'm facing is that I can submit an object that includes additional properties not specified in the IUser interface.

What would be the most straightforward and efficient approach to ensure that the user strictly adheres to the defined type, or alternatively, how can I clone it while maintaining only the properties outlined in the IUser interface?

Answer №1

My approach is to focus on creating a framework-agnostic solution. The goal is to address how TypeScript can restrict passing values of types with additional fields, emphasizing the need for exclusive behavior within the type itself.

It's important to note that enforcing such behavior solely at the type level may not always be practical. While compile-time checks can ensure type consistency, runtime validation becomes necessary when dealing with data from APIs.

To implement exclusive type behavior at the type level, consider the following:

type IUser = {
  name: string;
  lastname: string;
}

type OnlyExistingFields<Base, Extender> = {
  [K in keyof Extender]: K extends keyof Base ? Extender[K] : never
}

type IMoreUser = IUser & {
  age: number;
}

const user1: IUser = {
  name: 'John',
  lastname: 'Doe'
}

const user2: IMoreUser = {
  name: 'Jane',
  lastname: 'Doe',
  age: 30
}

declare function insertUser<U extends OnlyExistingFields<IUser, U>>(user: U): void

insertUser(user1) // 👍 correct type
insertUser(user2) // 🔴 error due to extra field

The above implementation ensures that only arguments of a specific type (or its exact subset) are accepted, maintaining type exclusivity.

While the type-level check is effective, it's crucial to acknowledge that runtime enforcement presents challenges. A runtime converter can help eliminate unwanted fields:

// Converter function to extract only IUser fields from an object
function toIUser<T extends IUser>(input: T): IUser {
    return {
      name: input.name,
      lastname: input.lastname
    }
}
const convertedUser = toIUser(user2); // convertedUser now has only IUser fields

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

A method to apply a class to the third <li> element using javascript

Can someone help me figure out how to add a class to the third element using Javascript? Here is the structure I am working with: <ul class="products-grid row four-columns first"> <li class="item"></li> <li class="item"></li&g ...

Unexpected Data Displayed by Material UI Modal Component

I'm currently facing an issue with my Material UI Modal component in a React/Typescript project. When a card element is clicked on the site, it should display expanded information in a modal view. However, clicking on any card only shows the most rece ...

Order a portion of a JSON array according to another part of the same array

Having a json array that needs sorting in JavaScript. The EventName field should match the respective Age fields like 01-10 Days and 10-20 Days. [ {Age: "01-10 Days", EventName: "Invoice AP Review", Value: 1, ActiveInvoices: []} ,{Age: "01-10 Days", Even ...

Ensuring the accuracy of user input in JavaScript, even after fixing a mistake and submitting again, will not cause the code to exit the else clause

I am currently working on a coupon code field that needs to accept a specific set of coupon keys. Below is the code I have written for validation. If a user enters an invalid key at first, they receive an alert saying "Invalid Key." However, if they corr ...

What is the best way to organize a json based on numerical values?

Can anyone guide me through sorting a JSON data into an array based on numeric value, and then explain how to efficiently access that information? {"362439239671087109":{"coins":19},"178538363954003968":{"coins":18},"234255082345070592":{"coins":137}} Th ...

I am currently studying react.js and struggling to comprehend how the deployment process for a react app functions

Will the server only serve the index.html file or is there a way for the client to run that html file as it's not a regular html file? Do I need a backend node to make it work? I'm having trouble understanding the entire process. Normally, a cli ...

The Angular project seems to be experiencing technical difficulties following a recent update and is

Recently, I made the transition from Angular 6 to 8 and encountered two warnings during the project build process that I can't seem to resolve. Despite searching online for solutions, nothing has worked so far. Any help would be greatly appreciated. ...

Is there a way to identify the items that have been removed and added in an array by comparing an old array to a new array

Consider the following scenario: oldArray = [ { id: 1, position: 'DEV OM'}, { id: 2, position: 'Senior Developer'}, ] newArray = [ { id: 2, position: 'Senior Developer'}, { id: 3, position: 'Junior Devel ...

The behavior of Datatables varies depending on the screen resolution

In my data table, there are numerous entries with child tables on each row of the main table. I am currently in the process of incorporating this type of functionality into my table, with a few modifications to create a table within the child row. You can ...

Vuetify's data table now displays the previous and next page buttons on the left side if the items-per-page option is hidden

I need help hiding the items-per-page choices in a table without affecting the next/previous functionality. To achieve this, I've set the following props: :footer-props="{ 'items-per-page-options':[10], &apo ...

Is there a way to update the input box value with a variable using jquery?

I am currently facing an issue with changing the value attribute of an input box in a form using jquery. Although I am able to change the value, it does not reflect in the outer html. Below is my current code snippet: $("a").click(function(event) { va ...

The functionality of the Angular directive ngIf is not meeting the desired outcome

We are currently working on transferring data from one component to another using the approach outlined below. We want to display an error message when there is no data available. <div *ngIf="showGlobalError"> <h6>The reporting project d ...

Does the downloading of images get affected when the CSS file has the disabled attribute?

Is it possible to delay the download of images on a website by setting the stylesheet to 'disabled'? For example: <link id="imagesCSS" rel="stylesheet" type="text/css" href="images.css" disabled> My idea is to enable the link later to tri ...

Request the generic password prior to revealing the concealed div

I want to implement a feature where a hidden div is shown once a user enters a password. The password doesn't need to be stored in a database, it can be something simple like 'testpass' for now. Currently, I have written some code using Java ...

Util Deprecations resolved with TSLint Autofix

Is there a feature in VSCode that can automatically fix deprecations related to the util library? For example: if (isNullOrUndefined(this.api)) { Would be better written as: if (this.api === null || this.api === undefined) { While there isn't an ...

"Experience the seamless navigation features of React Navigation V6 in conjunction with

Hello there, I've been experimenting with react-navigation 6 in an attempt to show a modal with presentation: "modal" as instructed on the documentation. However, I'm facing an issue where the modal is not displaying correctly and appears like a ...

Angular JS Troubleshooting: Application Not Functioning Properly

I've been learning AngularJS on codeSchool and I ran into an issue with my simple hello world app. It was working fine at first but then stopped completely. I can't seem to find the bug, so any help would be appreciated. Here is the HTML code: & ...

Utilizing LocalStorage with Angular 6 BehaviorSubject

I'm struggling with retaining data after refreshing a page. My approach involves using a shared service to transfer data between unrelated components. Despite extensive research on LocalStorage implementation and usage, I have not been able to find a ...

Utilizing visual representations for "symbol" within eCharts4r

I have been exploring the use of the "image" option for the symbol parameter in a tree chart with eCharts4r. Despite trying multiple methods, I am struggling to assign a unique image to each node in the tree instead of using a universal one. However, my a ...

Getting a ReferenceError while trying to use a MongoDB Collection variable in an external resolver file that had been imported through mergeResolvers

Here is a simplified example to illustrate the issue at hand. When using the resolver Query getAllUsers, the MongoDB Collection Users is not accessible in the external resolver file user.js. This results in the following error when executing the query: ...