Suggestions for crafting a type in typescript that ensures certain properties are excluded when employing the spread operator?

I have a situation where I need to send a backend model to the frontend with certain properties excluded, and I want to use typing to ensure these exclusions.

My initial attempt involved creating an interface for the model and then a restricted interface using Omit<> to exclude specific properties.

interface Thing {
    foo: string
    secret: string
}

interface RestrictedThing extends Omit<Base, "secret"> {}

const thing: Thing = { foo: "test", secret: "must_exclude_in_restricted"}

const restricted: RestrictedThing = { ...thing } //no warning is raised

However, TypeScript does not give a warning when using the spread operator to copy properties, even if they should not be part of RestrictedThing.

I came across ts-essentials StrictOmit, but it only validates the properties passed in, making it unsuitable for my needs.

I also attempted to use typeof but without success.

declare var { bar, ...forRestricted }: Thing;
type RestrictedThing = typeof forRestricted;

Is there a reliable method to create a copy of my Thing object that uses typing to exclude unwanted properties?

Any alternative approaches would be appreciated.

Answer №1

It's unfortunate that TypeScript's type system does not currently offer support for excess property checks on object literals that result from a spread operation. This limitation is well-known in the TypeScript community.

If you want to make sure that an object does not contain certain properties, you will have to manually verify those properties at runtime.

Utilize the is operator to confirm the type correctness and, within that function, remove the sensitive keys.

interface Thing {
  foo: string
  secret: string;
  secret2: string;
}
const restrictedKeys = ['secret','secret2'] as const;
interface RestrictedThing extends Omit<Thing, typeof restrictedKeys[number]> {}

const thing = {
  foo: "test",
  secret: "must_exclude_in_restricted"
};

const restricted: Partial<Thing> = { ...thing };

const cleanRestricted = (obj: Partial<Thing>): obj is RestrictedThing => {
  restrictedKeys.forEach(k => delete obj[k])
  return true;
};
if (cleanRestricted(restricted)) {
  // restricted is now really <RestrictedThing>
  restricted.secret = 'secret'; //throws error
}

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

Declaring a custom Angular Pipe

I've created a custom Pipe to filter a list of items and integrate it into my Angular/Ionic application. // pipes/my-custom-filter/my-custom-filter.ts import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'myCustomFilt ...

Is there a way to send map data using props in React?

I just want to store and pass the current props.url to the videomodal so I can show the same active video on the video modal. I can't use useState in the map. How can I pass it? Or is there any other solution? Videos.tsx ( props.url must be in the &l ...

Utilizing a configuration file with Vue's `use` method

Within my index.ts file, I am setting up the configuration for the Google reCAPTCHA component using a specific sitekey: Vue.use(VueReCaptcha, { siteKey: 'my_redacted_sitekey' }); This setup occurs prior to the initialization of the new Vue({ ...

Finding the final day of a specific year using the moment library

When it comes to determining the last day of a year, hard-coding the date as December 31st seems like a simple solution. While there are various methods using date, js, and jquery, I am tasked with working on an Angular project which requires me to use mom ...

Exploring Angular data iteration with Tab and its contentLearn how to loop through Tab elements

Upon receiving a response from the API, this is what I get: const myObj = [ { 'tabName': 'Tab1', 'otherDetails': [ { 'formType': 'Continuous' }, { 'formType& ...

What is the proper way to specify the return value of a function that has dynamically generated keys?

I am working with a TypeScript (v5.5.4) function called test that takes a fieldsMap parameter and is supposed to return a specific type based on the keys and values of fieldsMap. However, I am struggling to define the return type accurately. Here's th ...

"An issue arises as the variable this.results.rulesFired is not properly

I am faced with a set of table rows <tr *ngFor="let firedRule of splitRules(results.rulesFired); let rowNumber = index" [class.added]="isAdd(firedRule)" [class.removed]="isRemove(firedRule)" ...

Exploring the automatic type inference functionality of Typescript for generic classes

Although it may seem simple, I am struggling to pinpoint the cause of this error. I have been searching for a solution for quite some time, but I have yet to find one. class MyClass<T > { property: T = 5 // Error Here: Type '5' is not as ...

Ways to determine the generic type of a property value from a decorated property within a decorator

While experimenting with some code, I encountered an issue where the generic type of a property value wasn't being resolved correctly when changing from TValue to (t: TValue) => TValue. Instead of being recognized as the expected number, it was now ...

Creating a type-safe dictionary for custom theme styles in Base Web

In my Next.js project, I decided to use the Base Web UI component framework. To customize the colors, I extended the Theme object following the guidelines provided at . Interestingly, the documentation refers to the theme type as ThemeT, but in practice, i ...

Exploring Function Type in TypeScript: Utilizing both fat arrow and object literal type

Currently delving into the world of Typescript, I came across two methods for defining function types: using a fat arrow or an object literal. Here's an example: let myAdd1: (x: number, y: number) => number = function(x: number, y: number): n ...

Is it possible to pass a Styled Components Theme as Props to a Material UI element?

After spending 9 hours scouring the internet for a solution, I am at my wit's end as nothing seems to work. Currently, I am developing a React component using TypeScript. The issue lies with a simple use of the Material UI Accordion: const Accordion ...

What's the best way to invoke this specific TypeScript function?

I have come across a library that includes the following function declaration: import { Auth0JwtStrategy } from './strategy/auth0-jwt.strategy'; import { Auth0Service } from './auth0.service'; import { Auth0Options } from './auth0. ...

Ways to dynamically display or hide content in Angular 7

>when an English button is clicked, its corresponding div should be shown. If another button is clicked, its div should also show without closing the previous one. I want each div to close only when its respective button is clicked again. >Please not ...

Establish a permanent code folding feature in the Monaco editor for enhanced text organization

I need help implementing persistent code folding on the Monaco editor. Specifically, I am unsure about: how to extract the view state when it changes; storing it in localstorage; and then restoring it when Monaco is loaded. Although I am aware of saveVie ...

Is there something I'm missing? The action buttons cannot be displayed on a preview of the event

Currently in the process of developing an angular application featuring a calendar component to showcase events, I opted to utilize angular-calendar for the visual representation. While exploring the month view functionality, I encountered an issue where t ...

Encountering an issue with importing an enum: An error is triggered stating 'Variable implicitly has type 'any' in certain areas where its type remains undetermined.'

When I define simple enums in the same file, everything works fine. However, exporting/importing them causes numerous compilation errors related to types. It seems like the issue only arises when defining enums in a separate file, pointing towards a proble ...

retrieve information from Angular service

Is there a way for parent components to communicate with child components by injecting providers directly into the TypeScript file of each child component? I am trying to retrieve data using get and set methods, but I am unsure how to proceed. Any suggesti ...

The utilization of 'new' is not allowed with an expression that does not have a call or construct signature in TypeScript

While searching for a solution, I stumbled upon this link which unfortunately did not provide the answer I was looking for: Cannot use 'new' with an expression whose type lacks a call or construct signature I am facing a similar issue. In my JavaS ...

Upon receiving data from the Api, the data cannot be assigned to the appropriate datatype within the Angular Object

I am encountering an issue with the normal input fields on my page: https://i.stack.imgur.com/qigTr.png Whenever I click on the "+" button, it triggers an action which in turn calls a service class with simple JSON data. My intention is to set selectionC ...