Types have separate declarations of a private property in TS

avatar
Borislav Hadzhiev

Last updated: Feb 29, 2024
5 min

banner

# Table of Contents

  1. Types have separate declarations of a private property in TS
  2. Property is private in type 'X' but not in type 'Y' in TS

# Types have separate declarations of a private property in TS

To solve the error "Types have separate declarations of a private property", remove the private visibility modifier from members that have already been declared in the parent class and make sure you don't have multiple versions of the same package installed.

types have separate declarations for private property

Here is an example of how the error occurs.

index.ts
class Person { constructor(private name: string, private age: number) {} } // ⛔️ Class 'Developer' incorrectly extends base class 'Person'. // Types have separate declarations of a private property 'name'.ts(2415) class Developer extends Person { constructor(private name: string, private age: number) { super(name, age); } }

The Person class declares the name and age properties using the private visibility modifier.

The issue here is that the Developer class that extends from Person also declares the properties name and age.

To solve the error, remove the private visibility modifier from the properties in the child class.

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

remove private visibility modifier

The code for this article is available on GitHub

When class properties have private visibility, they can only be accessed from within the class that declared the properties (Person in the example).

# Using protected visibility instead

If you need to access the properties from subclasses of Person, declare them using protected visibility.

index.ts
class Person { // 👇️ protected (accessible from subclasses) constructor(protected name: string, protected age: number) {} } class Developer extends Person { constructor(name: string, age: number) { super(name, age); // 👇️ can access protected members console.log(this.name); console.log(this.age); } } const dev = new Developer('Bobby Hadz', 30);

using protected visibility instead

Protected members are accessible inside the class that declared them and its subclasses.

The code for this article is available on GitHub

# Using different versions of the same package

The error also occurs if we use different versions of the same package.

If you have multiple versions of the same package, your emitted code might contain the same class multiple times.

To resolve this, update your packages and make sure they don't depend on different versions of the same package.

If the error is not resolved, try to delete your node_modules and package-lock.json files, re-run npm install and restart your IDE.

shell
# 👇️ (Windows) delete node_modules and package-lock.json rd /s /q "node_modules" del package-lock.json del -f yarn.lock # 👇️ (macOS/Linux) delete node_modules and package-lock.json rm -rf node_modules rm -f package-lock.json rm -f yarn.lock # 👇️ clean npm cache npm cache clean --force npm install

Make sure to restart your IDE and development server if the error persists.

# 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.

# Remove the public identifier to solve the error

To solve the error, 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); } }
The code for this article is available on GitHub

# Using protected visibility instead

Private members are only accessible within the class.

If you want to make the properties accessible inside the subclass, 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 common cause of the error

Another cause of the 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.

# Using a setter and a getter to solve the error

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
The code for this article is available on GitHub

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.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.