Property is private in type 'X' but not in type 'Y' in TS

avatar

Borislav Hadzhiev

Fri Mar 25 20223 min read

banner

Photo by Kalen Emsley

Property is private in type 'X' but not in type 'Y' in TS #

The error "Property is private in type 'X' but not in type 'Y'" occurs when the visibility of a property is changed when a class extends another or implements an interface. To solve the error, use a setter and a getter with custom logic that suits your use case.

property private in type but not in type

Here are 2 examples of how the error occurs.

index.ts
class Person { constructor(private name: string, private age: number) {} } // ⛔️ Class 'Developer' incorrectly extends base class 'Person'. // Property 'name' is private in type 'Person' but not in type 'Developer'.ts(2415) class Developer extends Person { // 👇️ can't change visibility here constructor(public name: string, public age: number) { super(name, age); } } // ------------------------------------------------------------- interface Employee { salary: number; } // ⛔️ Class 'Tester' incorrectly implements interface 'Employee'. // Property 'salary' is private in type 'Tester' but not in type 'Employee'.ts(2420) class Tester implements Employee { // 👇️ can't change visibility here private salary = 0; }

In the first example, the Person class has a name and age private properties.

The Developer class that extends from Person tries to change the visibility of the properties and re-declares them.

We aren't allowed to change the visibility when extending a class or implementing an interface. To solve the error in this example, we have to remove the public modifier.

index.ts
class Person { constructor(private name: string, private age: number) {} } class Developer extends Person { constructor(name: string, age: number) { super(name, age); } }

Private members are only accessible within the class. If you want to make the properties accessible inside of the subclass, you can change their visibility to protected.

index.ts
class Person { // 👇️ protected (accessible in subclasses) constructor(protected name: string, protected age: number) {} } class Developer extends Person { constructor(name: string, age: number) { super(name, age); } logProps() { console.log(this.name); console.log(this.age); } }

If you need the class properties to be accessible from the outside, set them to public.

Another cause of the "Property is private in type 'X' but not in type 'Y'" error is when a class implements an interface and tries to set a property to private visibility.

index.ts
interface Employee { salary: number; } // ⛔️ Class 'Tester' incorrectly implements interface 'Employee'. // Property 'salary' is private in type 'Tester' but not in type 'Employee'.ts(2420) class Tester implements Employee { private salary = 0; }

Interfaces aren't allowed to define private or protected properties, because they are only concerned with the structure and capabilities of types.

If you need to declare a property that cannot be reassigned, use the readonly modifier.

index.ts
interface Employee { salary: number; } class Tester implements Employee { // 👇️ is readonly readonly salary = 0; } const tester = new Tester(); console.log(tester.salary); // 👉️ 0 // ⛔️ cannot reassign a read-only property tester.salary = 100;

The salary property can still be accessed from the outside, but it cannot be reassigned.

Alternatively, you can use a setter and a getter.

index.ts
interface Employee { salary: number; } class Tester implements Employee { // 👇️ private (only accessible in this class) private _salary = 0; // 👇️ accessible from outside get salary() { // 👉️ your implementation return this._salary; } // 👇️ protected (can access in subclass) protected set salary(num: number) { this._salary = num; } } const tester = new Tester(); console.log(tester.salary); // 👉️ 0

Consumers can still access the salary property from the outside, but you are able to provide an implementation for the getter method. For example, you could throw a helpful error message if you want to forbid this.

The _salary property is private and only accessible from within the class.

The salary setter is protected, so it is accessible inside of the class and its subclasses.

Use the search field on my Home Page to filter through my more than 1,000 articles.