In TypeScript, how to refer to the type of the current class

Is there a way to reference the current class type in the type signature? This would allow me to implement something like the following:

 export class Component{
  constructor(config?: { [field in keyof self]: any }) {
      Object.assign(this, config)
  }
}

The concept is to pass a configuration object that includes keys from the current class.

I could use interfaces for this purpose, but then I would have to repeat the same code in both the interface and the implementing class.

Another approach would be to utilize generics. For example:

export class Component<T>{
  init(config?: { [field in keyof T]?: any }) {
    Object.assign(this, config)
  }
}

class TestComponent extends Component<TestComponent>{
  foo: number
}
const component = new TestComponent().init({ foo: 11 })

However, the need to write

class TestComponent extends Component<TestComponent>
prompts me to explore alternative solutions...

Answer №1

To access the current class, consider utilizing the polymorphic this type approach

export class Component{
  initialize(config?: { [field in keyof this]?: this[field] }) {
    Object.assign(this, config)
  }
}

class TestComponent extends Component{
  foo: number
}
const component = new TestComponent().initialize({ foo: 11 })
const component2 = new TestComponent().initialize({ foo: "11" }) // error

Keep in mind you cannot utilize this as a type within the constructor

export class Component{
  constructor(config?: { [field in keyof this]?: this[field] }) { // mistake
    Object.assign(this, config)
  }
}

Answer №2

Does it function properly?

export class Component {
  test = 123;

  constructor(config?: { [field in keyof Component]: any }) {
      Object.assign(this, config)
  }
}


new Component({ test: 123 }) // valid
new Component({ test1: 123 }) // invalid

Playground

A shorter alternative could be:

constructor(config?: Component) {

It may not fully capture your intention, but it should suffice.

Surprisingly, even this is acceptable:

constructor(config = <Component>{}) {

This directly initializes an empty object as the starting point.

Source: utilizing this approach since TypeScript v1.

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

Execute a selector on child elements using cheerio

I am struggling to apply selectors to elements in cheerio (version 1.0.0-rc.3). Attempting to use find() results in an error. const xmlText = ` <table> <tr><td>Foo</td><td/></tr> <tr><td>1,2,3</td> ...

Proper method of managing undeclared declaration files (index.d.ts)

I encountered the following error message: error TS7016: Could not find a declaration file for module 'react-native-camera'. '/Users/ilja/Documents/Repositories/blok/node_modules/react-native-camera/index.js' implicitly has an 'an ...

Exploring dependency injection in Angular 1 using a blend of JavaScript and TypeScript

I'm currently working on integrating TypeScript into an existing Angular 1.5 application. Despite successfully using Angular services and third-party services, I am facing difficulties in injecting custom services that are written in vanilla JavaScrip ...

Determine the consistent type for numerous properties

Is it feasible to have Typescript automatically infer the type of multiple properties to be the same, or even infer the types based on a specific property? For example, consider the following code snippet -> interface Test<T> { value1: T; val ...

Displaying or concealing list elements in Angular 6

I am working on a simple Angular app that displays a list of items. I want the behavior to be such that when the first item in the list is clicked, its description (card) should be displayed. And, if the second item is clicked and its description is displa ...

I'm struggling to grasp the utilization of generics within the http.d.ts module in Node.js code

type RequestHandler< Request extends **typeof IncomingMessage = typeof IncomingMessage**, Response extends **typeof ServerResponse = typeof ServerResponse**, > = (req: InstanceType<Request>, res: InstanceType<Response> ...

What is the best way to guarantee that an object contains certain fields using Partial<>?

I am dealing with a function that accepts a parameter as shown below: const handleAccount = ( account: Partial<IAccountDocument>, ... ) => { ... } It is crucial that the interface for IAccountDocument cannot be modified to avoid requiring cer ...

Can the string literal type be implemented in an object interface?

My custom type is called Color, type Color = 'yellow' | 'red' | 'orange' In addition, I created an object with the interface named ColorSetting. interface ColorSetting { id: string yellow?: boolean red?: boolean orang ...

What sets enum with string values apart from a string type union in TypeScript?

When it comes to defining a variable with a predefined set of values in TypeScript code, there are two approaches - using an enum or using a union. For instance, imagine we have a button with various variants such as primary, secondary, and tertiary. We ...

Can you explain the significance of the additional pipeline in the type declaration in TypeScript?

Just recently, I defined a type as follows- interface SomeType { property: { a: number; b: string; } | undefined; } However, upon saving the type, vscode (or maybe prettier) changes it to- interface SomeType { property: | { a: nu ...

Angular is patiently awaiting the completion of the subscription

Currently, I am in the process of developing a test application using Angular. The challenge arises when I attempt to retrieve data through a Get request and then return a value based on that data. The code snippet below outlines the scenario: public getN ...

`Angular2 Reactively-shaped Form Elements with BehaviorSubject`

As a newcomer to Angular, I am struggling with updating reactive forms after making asynchronous calls. My specific challenge involves having a reactive form linked to an object model. Whenever there is a change in the form, it triggers an HTTP request th ...

Executing a component method from a service class in Angular

When trying to call a component method from a service class, an error is encountered: 'ERROR TypeError: Cannot read property 'test' of undefined'. Although similar issues have been researched, the explanations mostly focus on component- ...

Exploring the potential of React with Typescript: Learn how to maximize

Having some difficulties working with Amplitude in a React and Typescript environment. Anyone else experiencing this? What is the proper way to import Amplitude and initialize it correctly? When attempting to use import amp from 'amplitude-js'; ...

The Disabled element does not exhibit effective styling

When we include the disabled attribute in the text element, the style does not work. Can you explain why? <input pInputText [style]="{'padding-bottom':'10px','padding-top':'10px','width':'100%&apos ...

Automatic browser refresh with the `bun dev` command

Currently experimenting with the latest bun platform (v0.1.6) in conjunction with Hono. Here are the steps I followed: bun create hono test-api cd test-api bun dev After running the server, the following message appears: $ bun dev [1.00ms] bun!! v0.1.6 ...

Exploring the functionality of the scan operator within switchMap/mergeMap in RxJS

We're utilizing the scan operator to handle our 'load more' button within our table. This operator allows us to accumulate new results with the previous ones, but we've come across some unexpected behavior. Let's break it down by l ...

Does Vetur have additional undefined types in the type inference of deconstructed props?

When reviewing the code below, Vetur concluded that x,y are of type number | undefined. The presence of undefined is leading to numerous warnings when using x,y further in the code. Is there a way to eliminate the undefined from the type inference? <s ...

Loading data into the Nuxt store upon application launch

Currently, I'm working on an app using Nuxt where I preload some data at nuxtServerInit and store it successfully. However, as I have multiple projects with similar initial-preload requirements, I thought of creating a reusable module for this logic. ...

How to simulate loadStripe behavior with Cypress stub?

I am struggling to correctly stub out Stripe from my tests CartCheckoutButton.ts import React from 'react' import { loadStripe } from '@stripe/stripe-js' import useCart from '~/state/CartContext' import styles from '. ...