Last updated: Feb 29, 2024
Reading time·5 min
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.
Here is an example of how the error occurs.
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.
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.
class Person { constructor(private name: string, private age: number) {} } class Developer extends Person { // ✅ removed private modifiers constructor(name: string, age: number) { super(name, age); } }
When class properties have private
visibility, they can only be accessed from
within the class that declared the properties (Person
in the example).
protected
visibility insteadIf you need to access the properties from subclasses of Person
, declare them
using protected
visibility.
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);
Protected members are accessible inside the class that declared them and its subclasses.
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.
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.
# 👇️ (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.
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.
Here are 2 examples of how the error occurs.
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.
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.
public
identifier to solve the errorTo solve the error, remove the public
modifier.
class Person { constructor(private name: string, private age: number) {} } class Developer extends Person { constructor(name: string, age: number) { super(name, age); } }
protected
visibility insteadPrivate members are only accessible within the class.
If you want to make the properties accessible inside the subclass, change their visibility to protected.
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 error is when a class implements an interface and tries to set a property to private visibility.
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.
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.
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.
You can learn more about the related topics by checking out the following tutorials: