Extensible generic type/interface in Typescript

Looking to create a versatile base interface or type that can adapt its properties based on the generic object it receives. It might look something like this:

interface BaseObject<Extension extends object = {}>{
   a: string;
   b: string;
   {...Extension} <<< This syntax works in regular objects, but not in this context
} 

const sample:BaseObject<{x: number}> = {
    a: '123',
    b: '123',
    x: 123 <<<< Enforcing a type check here
}

Any ideas on how to implement this?

Answer №1

To achieve this, simply expand the interface.

interface EnhancedObject extends BaseObject {
  y: number;
}

const data: EnhancedObject = {
  a: 'abc',
  b: 'def',
  x: 456,
};

Answer №2

To achieve this functionality, one approach is to utilize mapped types with an Extension. TypeScript does have limitations when it comes to declaring types that use mapped types alongside property types or in an interface declaration. However, you can still create a type that combines the properties of Extension with the base properties by using an intersection, even though the syntax may seem a bit unusual:

type BaseObject<
  Extension extends object = {},
  All = Extension & { a: string; b: string }
> = {
  [K in keyof All]: All[K];
};

It's worth noting that the second generic property isn't strictly required. Alternatively, you could write it in the following manner:

type BaseObject<Extension extends object = {}> = {
  [K in keyof (Extension & { a: string; b: string })]: (Extension & {
    a: string;
    b: string;
  })[K];
};

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

There was an issue attempting to differentiate '[object Object]'. The Angular API Get Request from .Net only allows for arrays and iterables to be used

I am currently in the learning stage and consider myself a novice, so please forgive me if this question seems silly. I am working on a Movie Database project that involves integrating movies from a live API, creating a favorite list, implementing JWT auth ...

Incorporating a polling feature into an HTTP request within Angular 8

How can I implement a polling mechanism in order to fetch the status of a job (type Status) every minute for a service that requests this object with a specific JOB_ID as an argument? retrieveJobStatus$(JOB_ID): Observable<Status> { const url = ...

How can I create a join for my initial column in TypeORM?

I am trying to figure out how to create a verification email for my users, but I'm having trouble understanding how to connect the UserToken table with the user's id in TypeORM. Can someone provide some guidance on this? @Entity({name: "use ...

Utilizing ES6 JavaScript for Creating Static Methods and Angular 2 Services

During the development of an Angular 2 app involving multiple calculation services, I encountered some interesting questions: Is it beneficial to use static in an Angular service provided on the application level? Or is it unnecessary? How does a static ...

Looking for a method to efficiently populate an array with values in Typescript

Here is an example of how I work with arrays in my code: var alphas: string[]; alphas = ['abc1', 'abc2', 'abc3']; // (this array can be changed) My modal class looks like this: export class Team { TeamName: string; } To ...

Can a standard tuple be matched with its corresponding key?

This code snippet showcases a function that can recognize that the key "banana" cannot have the value "red": type Fruits = { banana: 'yellow' | 'green' strawberry: 'red' } const fruit = <K extends keyof Fruits>(modu ...

experimenting with the checked attribute on a radio button with jasmine testing

Currently using Angular 8 with Jasmine testing. I have a simple loop of radio buttons and want to test a function that sets the checked attribute on the (x)th radio button within the loop based on this.startingCarType. I am encountering false and null tes ...

Distinguishing between TypeScript versions 2.0.x and 2.1.x using type definitions and filtering with a switch/case statement

@ngrx/store (an observable redux implementation for angular (2) ) utilizes a specific pattern to assign the correct type to a reducer. Check out the actual code here. export const ActionTypes = { FOO: type('foo'), BAR: type('bar&apos ...

Issue with TypeScript: Error appears when importing express after running "npm i @types/express -D"

Struggling with adding the following line of code in an index.ts file: import express, { Application } from 'express'; Initially encountered an error with "from 'express'", so I ran npm i @types/express -D which fixed that is ...

Can data from an Angular app be accessed by an external JavaScript code within the same project?

I've been thinking about a theoretical scenario that luckily I haven't encountered yet. Imagine I have an Angular Project compiled in My PROJECT FOLDER. <br/> Inside this PROJECT FOLDER, there's another JAVASCRIPT FILE external to ...

What is causing my method chain to return a Promise<Promise<boolean?>> when using browser.wait(ExpectedConditions.presenceOf())?

Currently, I am in the process of creating some protractor tests that look like this: import { browser, element, by, ExpectedConditions } from 'protractor'; export class SomePage { private elements: any = {}; navigateToUpdate(name: string) ...

Issues related to the Angular Http module

When attempting to launch my app, I encountered the following error: ERROR Error: StaticInjectorError(AppModule)[ApiUserService -> HttpClient]: StaticInjectorError(Platform: core)[ApiUserService -> HttpClient]: NullInjectorError: No provide ...

The operation to assign a value to property 'two' cannot be completed as it is currently undefined

I'm facing an issue with the code below and cannot figure out why I am encountering the error message. I have ensured that each object contains a value, so why is there a reference to 'undefined'? Cannot set property 'two' of unde ...

Is it possible to devise a universal click handler in TypeScript that will consistently execute after all other click handlers?

In my ReactJS based application written in TypeScript, we have implemented various click handlers. Different teams contribute to the application and can add their own handlers as well. The challenge we face is ensuring that a specific global click handler ...

Firebase Promise not running as expected

Here is a method that I am having trouble with: async signinUser(email: string, password: string) { return firebase.auth().signInWithEmailAndPassword(email, password) .then( response => { console.log(response); ...

How can I reference MyClass.new as a method in Typescript?

Within my code, I have an array of objects and each object is structured like this: { id: 'string', name: 'string' } There's a class defined as follows: class User { constructor(obj: Record<string, string>) { Object.as ...

Keep going in the for await loop in NodeJS

My code snippet looks like this: for await (const ele of offCycles) { if ((await MlQueueModel.find({ uuid: ele.uuid })).length !== 0) { continue; } <do something> } I'm curious if it's possible to use a continue st ...

Reset the select boxes when a button is clicked

I'm currently utilizing Devextreme within my Angular application, and I have three dx-selectbox elements in the component. I am attempting to clear all three dropdown selections when clicking a "clear" button. Unfortunately, I am unable to find a way ...

What kind of impact on performance can be expected when using index.ts in a Typescript - Ionic App?

When setting up the structure of a standard Ionic app, it typically looks like this: app pages ----page1 ---------page1.ts ----page2 ---------page2.ts If I were to include an index.ts file in the pages folder as follows: pages/index.ts export { Page1 } ...

What is the best way to create a TypeScript function similar to a 'map' in React?

I recently started learning TS and am having trouble typing this arrow function: const mapLikeGet = (obj, key) => { if (Object.prototype.hasOwnProperty.call(obj, key)) return obj[key] } ...