How to understand "Property 'name' is private in type 'User'" in typescript

Viewed 579

I defined a class User which has a private field:

class User {
  private name: string = 'name'
  hello(): void {

  }
}

and a function uses the User type:

function testUser(user: User) {
}

Instead of creating an instance of User, I want to use an object to simulate it:

testUser({
  name: 'new-name',
  hello: () => {}
})

But it has a compilation error:

Argument of type '{ name: string; hello: () => void; }' is not assignable to parameter of type 'User'.
  Property 'name' is private in type 'User' but not in type '{ name: string; hello: () => void; }'.(2345)

I can't understand:

  1. The name is private in class User, why do we have to provide it in my mock object?
  2. Is it possible to provide a private 'name' in the mock object, or find a way not provide it without compilation error?

Living demo in playground

1 Answers

Private fields are a bit of an issue when trying to assign an object literal to where a class is expected. Typescript takes the position that since a private field is something that only de the declaring class can modify, it should not be aliasable.

You can only get around this with a type assertion. You could create a function that creates class mocks, by accepting only the public field of the class and does the type assertion internally to ensure the type assertion is not hiding other errors. The way to pick only public fields is to pass the type though Pick<T, keyof T>. Since keyof T only exposes public properties you end up removing the private ones:


function mock<T>(o: Pick<T, keyof T>): T {
  return o;
}

testUser(mock<User>({
  hello: () => {

  }
}))

Playground Link

Related