Issue TS2740 occurs when there are properties missing from a type while using the spread operator

My Angular application includes an object that mocks out an ActivatedRouteSnapshot. I've fully mocked out all the properties in this object. In order to create another mock object, I'm spreading the first object's properties into the second one.

export class AddEditResolverMocks {

    static routeWithId: ActivatedRouteSnapshot = {
        params: { id: 123 },
        data: { entity: EntityTypes.PayBillCycle },
        url: [],
        queryParams: {},
        fragment: '',
        outlet: '',
        component: '',
        routeConfig: null,
        root: new ActivatedRouteSnapshot(),
        parent: new ActivatedRouteSnapshot(),
        firstChild: new ActivatedRouteSnapshot(),
        children: [],
        pathFromRoot: [],
        paramMap: null,
        queryParamMap: null,
    };
    static routeWithoutId: ActivatedRouteSnapshot = {
        ...this.routeWithId,
    };
}

I initially expected all the properties to be brought over, but Visual Studio Code is showing a complaint:

Type '{ 
    url: UrlSegment[]; 
    params: Params; 
    queryParams: Params; 
    fragment: string; 
    data: Data; 
    outlet: string; 
    component: string | Type<any>; 
    routeConfig: Route; 
}' is missing the following properties from type 'ActivatedRouteSnapshot': 
 - root, 
 - parent, 
 - firstChild, 
 - children, 
 - and 3 more.ts(2740)

After letting Visual Studio Code refactor it, the "missing" properties are added and the error disappears. So why doesn't it work without explicit initialization? (I feel like I might be missing something obvious)

I'm also surprised that Visual Studio Code allows a this reference in a static initializer.

UPDATE: Changing this to AddEditResolverMocks:

 static routeWithoutId: ActivatedRouteSnapshot = {
        ...AddEditResolverMocks.routeWithId,
    };

had no effect.

UPDATE 2: I have now included the definition of ActivatedRouteSnapshot in the description as per a comment recommendation.

Answer №1

One issue that arises is the absence of certain properties in the definition of the ActivatedRouteSnapshot class, as these properties are actually getters and not attributes.

When a getter property exists without a corresponding setter, the "compiler" interprets it as read-only, requiring you to specify this attribute when creating an object instance.

Even if you provide the necessary attributes in a specific instance, the variable routeWithId is still defined as an ActivatedRouteSnapshot, which lacks these attributes.

To resolve the error, simply remove the variable definition:

export class AddEditResolverMocks {

    static routeWithId = {
        params: { id: 123 },
        data: { entity: EntityTypes.PayBillCycle },
        url: [],
        queryParams: {},
        fragment: '',
        outlet: '',
        component: '',
        routeConfig: null,
        root: new ActivatedRouteSnapshot(),
        parent: new ActivatedRouteSnapshot(),
        firstChild: new ActivatedRouteSnapshot(),
        children: [],
        pathFromRoot: [],
        paramMap: null,
        queryParamMap: null,
    };
    static routeWithoutId: ActivatedRouteSnapshot = {
        ...this.routeWithId,
    };
}

It's advisable not to instantiate objects in this manner. It's best to use the new operator and pass parameters through the constructor.

The constructor performs necessary operations with these parameters, which are omitted when instantiating objects in the current way. Additionally, the extra attributes being added should not belong to this class.

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

What is the reason for a boolean extracted from a union type showing that it is not equivalent to true?

I'm facing a general understanding issue with this problem. While it seems to stem from material-ui, I suspect it's actually more of a typescript issue in general. Despite my attempts, I couldn't replicate the problem with my own types, so I ...

What measures can be taken to avoid duplicating a string literal that serves as both a data type and a dynamic variable?

The EventBridgeEvent interface in the "@types/aws-lambda" package is defined as: export interface EventBridgeEvent<TDetailType extends string, TDetail> It's worth noting that TDetailType extends the string type. An interesting aspect ...

Tips for creating a universal function for two interlinked types

My goal is to establish an abstract relationship between different sub-types of Message and Response, allowing for a generic function that takes a Message as input and returns a corresponding Response. Specifically, when the function is called with type Me ...

Having trouble with firebase admin code completions not functioning properly in vscode?

I've attempted to install the Typescript integration for Firebase using: npm install --save-dev @types/firebase Unfortunately, I have not had any success. The "firebase-admin" and "firebase-functions" packages do not provide code completion or intel ...

Service function declaration results in the error message 'function is not a valid function.'

This particular service is designed to return an array of 1, 2, 3 for testing purposes. import {Injectable} from '@angular/core'; @Injectable() export class CitiesService { getCities() { return ['1', '2 ...

Transform Angular Material Table selection color with selection

Is it possible to customize the color of the selector in an Angular Material table when using selection? Learn more about it https://i.sstatic.net/5ZJQT.png ...

Is there a way to specifically call the last promise in a loop?

I'm new to promises and could use some help. I have a situation where promises are resolving randomly, how can I ensure that the last promise in the loop is resolved after the full loop executes? For example, if this.selectedValues has 4 values, som ...

Unable to load content from Three.js Examples library (Error loading script for "three/examples/jsm/loaders/OBJLoader2")

In my Angular application, I have a simple setup using Three.js. When I try to import the `OBJLoader2` from `three/examples/jsm/loaders/OBJLoader2`, everything works fine except when running it with the `ts_devserver`. The browser console shows an error: G ...

Getting the perfect typings installed from DefinitelyTyped

In my current attempt to install typings (version 1.3.2) for the malihu-custom-scrollbar-plugin, I am facing an issue with some wrong type identification error (Error TS1110: Type expected). This error is caused by the use of string literal types syntax li ...

The JSX element 'SubscribeCard' does not contain any construct or call signatures

I'm looking to implement the react-subscribe-card module for handling email subscriptions in my react.js project. Below is the code snippet from my popup.tsx file: import React from "react"; import SubscribeCard from "react-subscribe-c ...

Ionic 3 connection with WooCommerce store facing issues due to absent parameters

This is the code snippet I am working with: signup(){ let customerData = { customer : {} } customerData.customer = { "email": this.newUser.email, "first_name": this.newUser.first_name, "last_name": this ...

Form with placeholders

Is there a way to personalize an email using different variables, like adding special characters such as $, {}, [] around the word to indicate it's a variable? For example, {name}. I'm looking for a plugin compatible with Angular 14+ that can ass ...

What is the correct syntax for declaring a variable within a switch statement in TypeScript?

How can I properly use a switch statement in TypeScript to assign a new variable a value? For example: let name: string switch(index) { case 0: name = "cat" case 1: name = "dog" .... } I keep getting the err ...

Defining data types for vue-router meta section

Within my router.ts, I included some meta properties with a 'getter' that I plan to utilize when the component is loaded. { path: "attachments", name: "AdminJobsAttachments", meta: { navbarName: "Attac ...

Ionic Native HTTP call retrieves Blob without proper data type

I am currently working on a code snippet that extracts image strings and encodes them as Blob objects. const reqOptions: any = { method: 'get', responseType: 'blob', headers: { accept: 'image/*' } } ion ...

Encountering a problem while attempting to transfer data from a functional component to a class component in React with Typescript

In one of my pages, specifically the roleCategory.tsx (a functional component), I am utilizing the Navigate function to send a value named FromPage to another page called Home.tsx (which is a Class component). Below is the snippet of code where this functi ...

Trouble with displaying IonicV4 Menu Component in Split Pane

Currently, I am in the process of developing an app using Ionic V4. Despite following the documentation provided by Ionic, even the simplest tasks are proving to be quite challenging for me. My goal is to display a split pane with a side menu. The side me ...

Using the "compose" function with generic or anonymous arguments

Seeking a compose function that enables function composition. The ideal definition of compose should be type-safe, support any number of arguments, and handle generic or anonymous arguments accurately. However, I've encountered difficulties with the l ...

Tips for preventing repetition in http subscribe blocks across various components

Imagine a scenario where there is a service used for making HTTP request calls. There are two different components (which could be more than two) that need to send the same request using the same observables via this service. After receiving the result, it ...

Strategies for defining a ReactNode with optional props

I've been struggling for a while now trying to solve this issue without any success. I have a component that accepts two child nodes in the following structure: <SharedTwoColumns outer={{ className: "mt4 mb4" }} gap={<div className ...