What is the issue when using TypeScript if my class contains private properties while the object I provide contains public properties?

I am currently facing an issue while attempting to create a typescript class with private properties that are initialized in the constructor using an object. Unfortunately, I keep encountering an error message stating: "error TS2345: Argument of type 'TranslateResponse' is not assignable to parameter of type '{ status: "success" | "failed"; errorCode?: number | undefined; message?: string | undefined; data?: any; }'. 2023-05-30 13:45:24 translator-angular | Property 'status' is private in type 'TranslateResponse' but not in type '{ status: "success" | "failed"; errorCode?: number | undefined; message?: string | undefined; data?: any; }'. I'm confused about the significance of declaring a property as private or public within an object. Although I've come across similar issues concerning interfaces, I don't actually have any interfaces defined in my code.

export class FileTranslatedSuccess {
    
    private newFilePath!: string;
    private newFileName!: string;
    private targetLanguage!: LanguageCode;

    constructor(object: {newFilePath: string, newFileName: string, targetLanguage: LanguageCode}) {
        this.newFilePath = object.newFilePath;
        this.newFileName = object.newFileName;
        this.targetLanguage = object.targetLanguage;
    }

The constructor above takes an object of the following shape:

constructor(object: {
        fileTranslatedSuccess: {[key: string]: FileTranslatedSuccess[]},
        fileTranslatedFailed: {originalFile: string, targetLanguage: LanguageCode, message: string}[] | ""
    }) {
        let keys = Object.keys(object.fileTranslatedSuccess);
        this.fileTranslatedSuccess = {};
        keys.forEach(key => {
            this.fileTranslatedSuccess[key] = [];
            object.fileTranslatedSuccess[key].forEach(fileTranslatedSuccess => {
                this.fileTranslatedSuccess[key].push(new FileTranslatedSuccess(fileTranslatedSuccess));
            });
        });
        if (object.fileTranslatedFailed === "") {
            this.fileTranslatedFailed = "";
        } else {
            this.fileTranslatedFailed = [];
            object.fileTranslatedFailed.forEach(fileTranslatedFailed => {
                if (Array.isArray(this.fileTranslatedFailed)) {
                    this.fileTranslatedFailed.push(new FileTranslatedFailed(fileTranslatedFailed));
                }
            });
        }
    }

This constructor belongs to another object in my codebase. The error occurs when trying to instantiate the FileTranslatedSuccess class. (this.fileTranslatedSuccess[key].push(new FileTranslatedSuccess(fileTranslatedSuccess));). Can someone clarify why setting private properties in the constructor using an object with public properties results in an error?

Answer №1

object.fileTranslatedSuccess[key].forEach(fileTranslatedSuccess => {
    this.fileTranslatedSuccess[key].push(new FileTranslatedSuccess(fileTranslatedSuccess));
});

When working with TypeScript, it assumes that fileTranslatedSuccess is of type FileTranslatedSuccess. During compilation, TypeScript does not dynamically read the real-time value of fileTranslatedSuccess and only recognizes the public properties within the FileTranslatedSuccess class. Even if the values of newFilePath, newFileName, and targetLanguage are valid and accessible during runtime, TypeScript remains unaware.

This creates a dilemma for the TypeScript compiler. On one hand, you indicate that these 3 properties should be private but then proceed to request access to them in order to assign values from one instance to another.

To address this issue, there are several solutions:

  1. Make the properties public.

  2. Create getter functions for each property to retrieve their values. For example:

     export class FileTranslatedSuccess {
    
     private newFilePath!: string;
     private newFileName!: string;
     private targetLanguage!: LanguageCode;
    
     constructor(object: {newFilePath: string, newFileName: string, targetLanguage: LanguageCode}) {
             this.newFilePath = object.newFilePath;
             this.newFileName = object.newFileName;
             this.targetLanguage = object.targetLanguage;
     }
    
     getFilePath(): string {
         return this.newFilePath;
     }
    
     getFileName(): string {
         return this.newFileName;
     }
    
     getTargetLanguage(): string {
         return this.targetLanguage;
     }
    

    }

Subsequently, in your code, you can do something like the following:

object.fileTranslatedSuccess[key].forEach(fileTranslatedSuccess => {
    const filePath = fileTranslatedSuccess.getFilePath();
    const fileName = fileTranslatedSuccess.getFileName();
    const targetLanguage = fileTranslatedSuccess.getTargetLanguage();
    
    this.fileTranslatedSuccess[key].push(new FileTranslatedSuccess({newFilePath: filePath, newFileName: fileName, targetLanguage: targetLanguage}));
});
  1. If object.fileTranslatedSuccess originates from an API call and you aim to instantiate objects as FileTranslatedSuccess types, utilizing interfaces may provide more clarity. By making the 3 properties public in the interface and assigning them accordingly in your constructor, you enhance project readability. Here's a basic untested implementation:

     export interface IFileTranslatedSuccess {
         newFilePath: string;
         newFileName: string;
         targetLanguage: LanguageCode;
     }
    
    
     object.fileTranslatedSuccess[key].forEach((ifileTranslatedSuccess: IFileTranslatedSuccess) => {     
         this.fileTranslatedSuccess[key].push(new FileTranslatedSuccess(ifileTranslatedSuccess));
     });
    

In your FileTranslatedSuccess class, consider implementing:

export class FileTranslatedSuccess {
    
    private newFilePath!: string;
    private newFileName!: string;
    private targetLanguage!: LanguageCode;

    constructor(object: IFileTranslatedSuccess) {
       this.newFilePath = object.newFilePath;
       this.newFileName = object.newFileName;
       this.targetLanguage = object.targetLanguage;
       ...
    }
}

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

Guide to populating a list in a resolver during navigation and storing the initial item in the ngrx store

I recently incorporated ngrx into my application to manage the data centrally. However, I am facing challenges with loading the initial data and navigating to a default value. This has raised questions regarding the best approach to utilizing ngrx while re ...

Tips for properly handling a property that receives its value from a callback function and waiting for it to be updated

Below is my TypeScript code: private getInfoSystem = () => { this.systemInfo = { cpuSpeed: 0 , totalRam: os.totalmem(), freeRam: os.freemem(), sysUpTime: os_utils.sysUptime(), loadAvgMinutes: { on ...

Instead of returning an object, the underscore groupBy function now returns an array

Currently, I am attempting to utilize underscore to create an array of entities that are grouped by their respective locations. The current format of the array consists of pairs in this structure { location: Location, data: T}[]. However, I aim to rearran ...

What is the method for accessing an anonymous function within a JavaScript Object?

Currently facing an issue with a Node.js package called Telegraf, which is a bot framework. The problem arises when trying to create typings for it in TypeScript. The package exports the following: module.exports = Object.assign(Telegraf, { Composer, ...

Implementing Constants in Angular 2: Best Practices

Within my Angular 2 project, I have a crucial object known as translation that stores various strings utilized in multiple forms. This global configuration appears as follows: public translator = { 'performance_standard_time_deviation&apo ...

Lack of Intellisense in Sveltekit for the generated $types module on WebStorm

Is there a setting in WebStorm to enable intellisense for automatically generated ./$types by SvelteKit? I'm writing without any minimal example, just curious. Everything is done according to SvelteKit's documentation. Using satisfies LayoutLoad ...

How can you programmatically toggle the visibility of a material table footer?

Is it possible to control the visibility of the material table footer using an @Input() variable? I am working on a custom table component that may or may not need a footer, like this <my-component [showFooter]="false"></my-component> My init ...

Is there any need for transpiling .ts files to .js when Node is capable of running .ts files directly?

If you are using node version 12, try running the following command: node hello.ts I'm curious about the purpose of installing typescript globally with npm: npm install -g typescript After that, compiling your TypeScript file to JavaScript with: ...

What is the best way to trigger click events within a select dropdown using Angular?

I have implemented two buttons (month, year) that trigger different events. Now, I want to replace these buttons with a select element. Can you guide me on how to achieve this? Here is my current code: // Button implementation <button class="menu-butt ...

Retrieve the output of the subscribe function in Angular 8 service

I have a service with a method that retrieves the profile image of a user. users.service.ts getPictureProfile() { const headers = new HttpHeaders({ . . .}); const options = { headers }; const body = {...}; return this.http.post(environmen ...

Angular: Utilizing Parameters in HTTP GET Requests

I've recently started using Angular. Currently, I'm working on sending a parameter in an HTTP GET request. This is what my code looks like: for (var i = 0, len = this.recentArtists.topartists.artist.length; i < len && i < h ...

Issues regarding ambient getters and setters

Recently, I encountered an issue with my open-source library called Firemodel. The library utilizes ES classes and getters/setters within those classes. Everything was working smoothly until my VueJS frontend code started flagging every instance of these g ...

Error in Reactive Form: Null Property Reading Issue

Issue: Encountered a Cannot read property errors of null error in the form group. I have implemented a reactive form with validation, but I keep running into this specific error. Here is the complete form control setup: <div class="container mt- ...

Struggling to utilize a personalized filter leads to the error message: "Unable to call a function without a designated call signature."

Trying to use a custom filter from an Angular controller is resulting in the error message: 'Cannot invoke an expression whose type lacks a call signature'. I successfully implemented this on my last project, so I'm confused about what coul ...

Developing specialized error messages embedded within backend feedback using Angular

In my Angular8 application, the server consistently provides responses in the 200s series. Any errors from the server are encapsulated within the Response object, which means I have to generate errors from it. A standard response looks like this: The APP_ ...

A more efficient approach to specifying types for the 'navigation' object in React Native's Stack Navigator

Struggling with modularizing prop types in React Navigation, particularly when using TypeScript. The Typescript section of the React Navigation documentation suggests defining types for each screen props in this manner: //types.ts export type RootStackPara ...

TypeScript: implementing function overloading in an interface by extending another interface

I'm currently developing a Capacitor plugin and I'm in the process of defining possible event listeners for it. Previously, all the possible event listeners were included in one large interface within the same file: export interface Plugin { ...

A guide on determining the return type of an overloaded function in TypeScript

Scenario Here is a ts file where I am attempting to include the type annotation GetTokenResponse to the function getToken. import { ConfigService } from '@nestjs/config'; import { google, GoogleApis } from 'googleapis'; import { AppCon ...

It is not necessary to specify a generic type on a Typescript class

When working with Typescript and default compiler options, there are strict rules in place regarding null values and uninitialized class attributes in constructors. However, with generics, it is possible to define a generic type for a class and create a ne ...

In Angular, I aim to invoke the this.addDispatchToReceive method whenever the outcome is successful within each forEach iteration

How can I ensure that the values from this.stockItemDispatch are obtained in this.addDispatchToReceive(); during each iteration of a loop, instead of only getting the last stock value? The issue is that the subscribe function runs after the foreach cycle ...