Is it possible to have Partial<SomeClass> without any methods included?

When creating a class, I like to include a constructor that can accept any relevant members for the class:

class AnotherClass {
  itemA: string;
  itemB: number;

  constructor(obj: Partial<AnotherClass>) {
    Object.keys(obj).forEach(key => this[key] = obj[key]);
  }
}

This way, I have the flexibility to instantiate objects using

new SomeObject({itemA: 'example'})
, new SomeObject({itemB: 5}), or a combination of properties.

(In this scenario, let's assume it's a casual project and we're disregarding any reasons against formatting the constructor in this manner.)

While this approach is useful, it can clutter Intellisense with all available methods in addition to properties (even though my example doesn't contain methods).

Is there a variation or condition for Partial<AnotherClass> that restricts it to only properties? Since I tend to use arrow functions frequently, I suppose these would be non-function properties (given that arrow functions are technically considered properties rather than methods).

Answer №1

If you want to retrieve keys from an object that are not functions, you can achieve this by using a mapped + conditional type like the following:

type NonMethodKeys<T> = {
    [K in keyof T]: T[K] extends Function ? never : K
}[keyof T]

This type iterates through all keys of an object, and if the value is a function, it assigns the property type as never, otherwise it keeps the key K. By indexing with [keyof T], you get a union of keys that are not associated with functions.

You can then use these keys with the Pick utility type to create a new type without the method keys.

type WithoutMethods<T> = Pick<T, NonMethodKeys<T>>

An example usage would look like this:

type A = WithoutMethods<{ a(): number, b: string}> // results in type: { b: string }

In your scenario, you can apply it in a constructor like so:

constructor(obj: Partial<WithoutMethods<SomeClass>>) { /* ... */ }

If you are using TypeScript 4.1 (currently in beta), there is a more straightforward way to achieve this using Key Remapping in Mapped Types and an as clause for mapping keys to never.

type WithoutMethods<T> = {
    [K in keyof T as
        T[K] extends Function ? never : K
    ]: T[K]
}

type A = WithoutMethods<{ a(): number, b: string}> // results in type: { b: string }

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

Verify if the array entries match

Within my select element, I populate options based on an array of values. For example: [{ name: 'A', type: 'a', }, { name: 'B', type: 'b', }, { name: 'B', type: 'b', }, { name: &apos ...

Struggling to design a versatile Angular Material dialog component for effortless reusability

I am currently working on developing a versatile Angular component that serves as a container for Material Angular dialogs. My aim is to be able to provide a child component or template to the container component and then utilize the MatDialog service to o ...

Best practices for creating a versatile modal component

I have come across a few examples, but they all appear to be contradictory or intended for older versions of ng-bootstrap. What is the correct method for creating a basic modal that can be stored in a shared directory and then used for multiple modals on ...

The function you are trying to call is not valid... the specified type does not have any call signatures [ts 2349

Having some trouble using functions from Observable Plot example with a marimekko chart in my TypeScript project. I encountered an error on this particular line: setXz(I.map((i) => sum.get(X[i]))) The code snippet causing the issue is as follows: fu ...

The forwarded reference of the material-ui component is consistently empty

Currently, I am exploring the creation of a navbar with a drawer element using the material-ui library. I am attempting to pass the <Drawer> Component to the parent navbar so that I can access the toggleDrawer function within my NavDrawer component. ...

What method can be used to identify the type of storage: SessionStorage or LocalStorage?

After finding that my variable is of type Storage according to variable.constructor.name, I am now looking for a way to identify whether it is localStorage or sessionStorage. I simply need to retrieve the name. https://i.sstatic.net/kfPYU.png Code exampl ...

Dealing with asynchronous operations in a pipeline with fp-ts

I'm currently exploring fp-ts and have been contemplating how to restructure my functions in order to steer clear of nested folds. While many online examples showcase a clean invocation of the pipe function, I am struggling to eliminate the nested fol ...

Troubleshooting the NullInjectorError in Angular - Service Provider Missing?

I'm facing an issue in my code where I have buttons that should trigger pop-ups displaying details as a list when clicked. However, every time I click the buttons, I encounter the error mentioned below. It seems like I am unable to access the desired ...

Steps to initiate or conclude a conversation from a designated location?

I'm working on an Angular project where I have a popup dialog open. However, I want the dialog to appear from the button and close within the button itself, similar to this example: https://material.angularjs.org/latest/demo/dialog Opening and closin ...

Tips for managing the dimensions of the <label> element within a React component

I'm facing an issue where the element size is not matching the box size as expected. Additionally, the width property doesn't seem to work in React. Does anyone know how to solve this problem? const DragDrop = () => { ... return ( &l ...

Exploring nested keys within JSON data using TypeScript

I am currently working with this object structure { "Monday": [ { "morning": [ { "start_time": "02:00", "end_time": "07:3 ...

Exploring methods in Firebase Cloud Functions to retrieve and modify values

I'm currently attempting to retrieve a value from a specific location in my database, add 1 to it, and then update it back. However, I keep encountering various errors, with the most recent being: TypeError: Cannot read property 'update' of ...

What is the best way to terminate a Node.js app using a scheduler?

I've been attempting to halt my cron task and shut down the entire nodeapp after 5 executions, but despite trying various methods, all attempts have failed. The message "time to quit" continues to appear in the log every minute. What would be the mos ...

node-ts displays an error message stating, "Unable to locate the name '__DEV__' (TS2304)."

I recently inserted __DEBUG__ into a TypeScript file within my NodeJS project. Interestingly, in VSCode, no error is displayed. However, upon running the project, I encounter an immediate error: error TS2304: Cannot find name '__DEBUG__'. I att ...

Issue with Moment Js: Unable to change date with time zone function

Trying to convert a UTC date and time to local time ("Europe/Paris") using moment's timezone function, but encountering issues. The code I am using is: var m = moment.tz(this.startTime, 'Europe/Paris'); this.startTime = m.format("YYYY-MM-DD ...

Activating the microphone device on the MediaStream results in an echo of one's own voice

I am in the process of creating an Angular application that enables two users to have a video call using the Openvidu calling solution. As part of this application, I have implemented a feature that allows users to switch between different cameras or micr ...

What is the reason behind the failure of this RecursivePartial implementation to properly handle Dates?

Exploring the topic of implementing a recursive partial in typescript, a question on Stack Overflow sparked some interesting discussions. The answers provided seemed promising, but upon further examination, the latest answer pointed out their incompletenes ...

Creating and Injecting Singleton in Angular 2

I have a custom alert directive set up in my Angular app: import { Component } from 'angular2/core'; import { CORE_DIRECTIVES } from 'angular2/common'; import { Alert } from 'ng2-bootstrap/ng2-bootstrap'; @Component({ sele ...

Navigating to specific rows in a primeng virtualscroll table using the scrollToIndex

Utilizing Primeng virtual scroll table in Angular to manage large datasets in an array. I am interested in using the scrollToIndex. Is there an equivalent of cdk-virtual-scroll-viewport in Primeng table? I need the functionality where, upon a user clicking ...

Trouble with expanding multiple rows in an Angular nested mat table functionality

I recently built a nested mat-table grid using Angular Material. However, I am facing an issue where only one row can be expanded at a time. I am looking for a solution to allow multiple rows to be expanded simultaneously without automatically collapsing t ...