What purpose does a private property serve within the interface?

Given the following code snippet:

class X  {
    bar() {
        return "bar"
    }
    constructor(private readonly x: number){}
}

interface Y extends X {
}


const f = (y: Y) => { console.log(y.bar()); }

f({ bar: () => "tavern"});

The code does not compile due to the missing x.

f({ bar: () => "tavern", x: 1});

Another attempt that fails to compile because x is not private.

Trying to rewrite the code to ensure that x can be declared as private results in this rejected solution:

class Y implements X {
    bar() {
        return "tavern"
    }
    private x = 1;
}

This approach is ineffective due to the issue of "types having separate declarations."

The only viable solution discovered so far involves removing the private keyword from the constructor.

Ideally, the preference is for the initial solution where there's no concern about private properties or members within the constructor.

Two main questions arise:

  1. Why does this occur?
  2. Is there a way to avoid dealing with private properties altogether?

Answer №1

Ryan Cavanaugh, the development lead for Microsoft's Typescript team, shared his thoughts in a comment:

He emphasized that allowing private fields to be missing would not just be a minor issue, but a significant problem affecting the overall soundness of the code.

To illustrate this point, consider the following code:

class Identity {
  private id: string = "secret agent";
  public sameAs(other: Identity) {
    return this.id.toLowerCase() === other.id.toLowerCase();
  }
}

class MockIdentity implements Identity {
  public sameAs(other: Identity) { return false; }
}

In this example, MockIdentity seems like a compatible version of Identity, but using it as such will cause a crash in the sameAs method when a non-mocked instance interacts with a mocked one.

This situation is frustrating and can lead to problems.

However, a workaround was discovered to address this issue:

type Public<T> = {
    [P in keyof T]: T[P];
};

class X  {
    bar() {
        return "bar"
    }
    constructor(private readonly x: number){}
}

interface Y extends Public<X> { }

const f = (y: Y) => { console.log(y.bar()); }

f({ bar: () => "tavern"});

This workaround allows for mocking complex types effectively without having to mock out private data as well.

It is important to note that this approach is primarily intended for use in testing contexts where interactions between mocked and genuine instances are limited.

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

Displaying an error message in a spreadsheet cell

Issue The problem arises when viewing the exported excel file where undefined is displayed. However, upon investigation, there are no empty array indexes causing this confusion. Solution Attempt const joinDate = new Date(obj.date); let snap = [ obj. ...

Why are nested RxJS map operators used and how do they impact data transformation?

Recently, I enrolled in an online Angular course and discovered that RxJS plays a significant role in web development. While exploring different concepts, I encountered a nested map operator that intrigued me. Although I can somewhat decipher what is happe ...

Tips for dynamically calling a property member of a function type in Typescript

How can I determine if a member is a function in TypeScript? Is dynamic typing discouraged in TypeScript? function checkIfFunction<T, K extends keyof T>(obj: T, propName: K) { if (typeof obj[propName] === "function") { obj[p ...

What is the best way to ensure that Interface (or type) Properties always begin with a particular character?

I attempted to tackle this assignment using template literals, but unfortunately, I wasn't successful. Here is the interface that I am working with: interface SomeInterface { '@prop1': string; '@prop2': string; '@ ...

AngularJS 2 TypeScript structure

My application includes a user service for managing user operations and an interface for the user object. user.service.ts import {Injectable} from 'angular2/core'; export interface User { name: string; email?: string; picture?: string; } ...

Is the state variable not being properly set by using React's setState within the useCallback() hook?

Within a React FunctionComponent, I have code that follows this pattern: const MyComponent: React.FunctionComponent<ISomeInterface> = ({ someArray, someFunction }) => { const [someStateObjVar, setSomeStateObjVar] = React.useState({}); const [ ...

What is the best way to invoke a function that is declared within a React component in a TypeScript class?

export class abc extends React.Component<IProps, IState> { function(name: string) { console.log("I hope to invoke this function"+ name); } render() { return ( <div>Hello</div> ); } } Next, can I cal ...

What is the best way to retrieve distinct objects based on LocId across all locations?

Encountering an issue while working on Angular 7: unable to return distinct or unique objects based on LocId. The goal is to retrieve unique objects from an array of objects containing all Locations. allLocations:any[]=[]; ngOnInit() { this.locationsServ ...

Learn how to utilize a Library such as 'ngx-doc-viewer2' to preview *.docx and *.xlsx files within the application

After 3 days of searching, I finally found a solution to display my *.docx and *.xlxs files in my angular application. The API returns the files as blobs, so my task was to use that blob to show the file rather than just downloading it using window.open(bl ...

Establishing the correct data type to be returned from a fetch function in order to align with a specific custom type

My app has two interfaces defined: export interface Job { job_title: string, employer: string, responsibilities: string[] achievements: string[], start_date: string, end_date: string } export interface CreatedJob extends Job { ...

Which is the optimal choice: subscribing from within a subscription or incorporating rxjs concat with tap?

After storing data in the backend, I proceed to retrieve all reserved data for that specific item. It is crucial that the data retrieval happens only after the reservation process to ensure its inclusion. Presented with two possible solutions, I am cont ...

What could be causing the error when my file is running?

Whenever I attempt to run a file using the command node database.ts, an error pops up. Can someone help me identify what's wrong with my syntax? This is how the file appears: import { Sequelize } from 'sequelize-typescript'; export const ...

I am encountering a CORS error in Nest.js despite having CORS enabled

I'm currently working on a project using next.js for the frontend and nest.js for the backend. Despite having CORS enabled in my main.ts file of nest.js, I keep encountering CORS errors. Below is an excerpt from my main.ts file: import { NestFac ...

What is the process for choosing a specific id from a JSON structure?

Is there a way to extract specific data from a JSON format within an Ionic project? What is the process for selecting the ID associated with particular data in a JSON format? And how can I retrieve and display the value linked to the selected product&apos ...

Accessing properties within nested objects in a class

In my Angular 7 application, I have two object classes filled with data - employee and company (data retrieved through a web API from a database). The Employee class has fields - emp_id, name, surname, and a company object. The Company class has - c_id, ...

Could a variable (not an element) be defined and controlled within an Angular 2 template?

For instance, envision a scenario where I have a series of input fields and I wish to assign the 'tab' attribute to them sequentially as we move down the page. Rather than hard-coding the tab numbers, I prefer to utilize a method that automatical ...

Utilizing Async/Await with Node.js for Seamless MySQL Integration

I have encountered two main issues. Implementing Async/Await in database queries Handling environment variables in pool configurations I am currently using TypeScript with Node.js and Express, and I have installed promise-mysql. However, I am open to usi ...

Encountering error code TS1003 while trying to access object properties using bracket notation in Typescript

How can object property be referenced using bracket notation in TypeScript? In traditional JavaScript, it can be done like this: getValue(object, key) { return object[key]; } By calling getValue({someKey: 1}, "someKey"), the function will return 1. H ...

What is the reason for the lack of compatibility between the TypeScript compilerOptions settings 'noEmitOnError: true' and 'isolatedModules: false'?

Whenever I try to execute TypeScript with isolatedModules set as true and then false, I keep encountering this error message: tsconfig.json(5,9): error TS5053: Option 'noEmitOnError' cannot be specified with option 'isolatedModules'. ...

Customize the text for the material icon

Can I customize an icon by using the following code: import FiberNewIcon from "@mui/icons-material/FiberNew"; Is there a way to add custom text to the icon? ...