How can an interface be "streamlined" or "simplified" in TypeScript?

Within a complex project encompassing multiple front-end applications and dozens of microservices, we maintain a private npm repository housing common components utilized by these front-end apps. These shared components include TypeScript models such as:

interface IUser {
    id: string;
    login: string;
    name: string;
    ...
}

While this setup ensures consistency among the apps, the rapid development pace can result in discrepancies in the data returned by various microservices. For instance, a microservice might return an "enriched" object that extends the common interface:

interface IUser {
    id: string;
    login: string;
    name: string;
    ...
    extraField1: someType1;
    extraField2: someType2;
}

To address such discrepancies, enriched types can be defined through interfaces that extend the base commons interface:

interface IUserEnriched extends IUser {
    extraField1: someType1;
    extraField2: someType2;
}

However, there are cases where a microservice returns a simplified object:

interface IUserImpoverished {
    id: string;
    /* no login: string; here; or may be it's optional, unlike in the common interface */
    name: string;
    ...
}

I am curious if TypeScript offers a way to automatically generate such impoverished interfaces based on IUser instead of duplicating code (?). This poses challenges when updating the commons: adding fields to IUser may not affect all applications immediately, but removing a property like login requires creating enriched interfaces wherever it is used. The ability to simplify interfaces would be beneficial in such scenarios.

I attempted researching using terms like "narrow [TS interface]" but couldn't find relevant information. If you are familiar with the correct terminology, please share your insights.

Answer №1

To manipulate object types in TypeScript by removing specific properties, you can utilize the Omit<T, K> utility type. This allows you to "impoverish" the object type T by omitting properties with keys of type K. Here's how you can create a type alias:

type TUserImpoverished = Omit<IUser, "login">;

If you prefer an interface, you can define it like this:

interface IUserImpoverished extends Omit<IUser, "login"> { }

It's important to note that the second parameter in the omit function specifies the string literal type "login". By using this approach, you can see that the omitted key is no longer present among the known keys of the resulting object type:

const impoverishedUser: IUserImpoverished = { id: "1", name: "Alice" };

If you need to remove multiple keys, you can achieve this by creating a union of the relevant key types for K:

type TUserFurtherImpoverished = Omit<IUser, "login" | "name">;
const furtherImpoverishedUser: TUserFurtherImpoverished = { id: "2" };

Hopefully, this explanation proves helpful to you. Best of luck with your TypeScript endeavors!

Click here for Playground link to code

Answer №2

It's a bit unclear what you're trying to achieve, but one way to approach it is by manipulating utility types like this:

interface IUser {
  id: string;
  name: string;
}

type IUserSubset = Pick<IUser, 'id'>;

const subsetUser: IUserSubset = {
  id: 'example'
};

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

Referring to a component type causes a cycle of dependencies

I have a unique situation where I am using a single service to open multiple dialogs, some of which can trigger other dialogs through the same service. The dynamic dialog service from PrimeNg is being used to open a dialog component by Type<any>. Ho ...

Retrieve functions contained within the component.ts file of an Angular library: tips and tricks

I have developed an Angular library, named 'mylib', where I have utilized only the mylib.component.ts file. The HTML element codes are included inside the template variable of this file, along with the functions responsible for modifying these el ...

What's the best way to track changes in multiple form fields simultaneously in Angular?

Situation I have a form with 8 fields, but I want to monitor changes in just three of them to apply the same function. I don't want to set up individual subscriptions for each field like this: this.headerForm.get('start').valueChanges.subsc ...

Combining objects in a JavaScript array based on a specific property

Here is an array I have: var array = [ { category: 'Input', field: 0, value: '17' }, { category: 'Input', field: 0, value: '5' }, { category: 'Input', field: 0, value: '8' }, ...

Tips for creating a mapped type in TypeScript that is based on an array

Is there a way to create a function with dynamic properties? function magic(...propertyNames:string[]): { ????? : any } { .... } Could the returned type have properties listed in propertyName? For instance: type ResultType = {alpha:any, bravo:any}; le ...

What is the best method to add data to a child array located within a nested array?

Struggling to create an array that will display data in the following format: Healthcare -- Insights driven by data for improved healthcare -- Urban Analytics Transport -- Urban Analytics Cities -- Urban Analytics I have attempted ...

Acquire Binance account balances through NextJS, ccxt library, and TypeScript integration

Currently, I am attempting to retrieve balances from Binance within my NextJS 13 application, utilizing the /src/app directory along with TypeScript. async function fetchData() { const exchange = new ccxt.binance ({ "apiKey": "mykey ...

Can you identify the specific syntax for a 'set' function in TypeScript?

I have a TypeScript function that looks like this: set parameter(value: string) { this._paremeter = value; } It works perfectly fine. For the sake of completeness, I tried to add a type that specifies this function does not return anything. I experimen ...

Deciphering the SessionProvider error: When "useSession" isn't recognized as a function

I recently started diving into React and NextJS, but I've been able to piece things together with the knowledge I have. Recently, I added social login functionality using Lucia auth and now I'm looking to implement a session provider to allow ac ...

Consider pushing items onto an array only once when the condition is met, instead of adding to the array every

I have been tasked with importing Excel files containing customer orders into my web application. The process involves converting the data in the file into an object of arrays, where each array represents a row from the Excel sheet. Once the data is impor ...

The error code TS2345 indicates that the argument '{ read: typeof ElementRef; }' cannot be assigned to the parameter '{ read?: any; static: boolean; }'

Currently in the process of updating my Angular application from version 7 to version 8. Upon running ng serve, I encounter the following error: Error TS2739: Type '{}' is missing the following properties from type 'EmployeeModel': stat ...

`Database Schema Enforcement in Firestore: Custom Objects vs Security Rules`

Firestore, being a noSQL database, is schemaless. However, I want to ensure that the correct data type is being passed in. Custom Objects As per Firebase documentation, https://firebase.google.com/docs/firestore/manage-data/add-data class City { const ...

Utilize mui-tiptap to effortlessly upload images to your content

My current project involves using the mui-tiptap module in React 18 with Vite. Specifically, I am facing an issue with uploading a local image to my backend. The problem seems to lie in my frontend code, as I am encountering a TypeScript error that is prev ...

Exploring the power of Supabase's two-tiered joins using TypeScript

After reviewing the documentation here, I managed to successfully implement the first level join (agent_profile) but encountered issues when trying to join the next level (agent_office). Although the query returns the correct data, both VS Code and my app ...

After the click event, the variable in the Angular .ts file does not get refreshed

Great! I have a service in my .ts component that loops through an array of court names. Every time I click on a next or back arrow event, a counter is incremented starting at 0, where index 0 corresponds to field 1 and so on. The issue I'm facing is ...

What is the best way to apply multiple array filters to an object list in react.js?

Looking to filter an array of items using multiple filter arrays in order to display only the items that match all selected filters. For example: The main array contains a table with the following data: ID TypeID LocationID Name 1 2 ...

Leverage asyncData method in your NuxtJS layout or component

Is there a way to incorporate asyncData into a layout or component even though it seems to be forbidden? The reason I'm asking is because my sidebar component is used in the default layout, and I want to utilize asyncData to display data fetched from ...

Traverse a nested array containing children elements to construct a pathway map

I am currently working with a multidimensional array that contains children (subcategories): As I am setting up Angular routing, I receive this data format from an API. const items = [{ displayName: 'News', urlName: 'news', subca ...

What is the best way to divide an HTML table into two sections?

I'm looking to organize my data into a table with two separate sections, one on the left and one on the right. For example, if I have 20 rows of data, I want to display the first 10 rows on the left side with headers and the remaining 10 rows on the r ...

Methods to acquire the 'this' type in TypeScript

class A { method : this = () => this; } My goal is for this to represent the current class when used as a return type, specifically a subclass of A. Therefore, the method should only return values of the same type as the class (not limited to just ...