Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript: make subclass with writable properties

Tags:

typescript

I am trying to define a type T where all properties of T are non-readonly (writable), but still assignable to T. However, this does not seem to work when there are private/protected properties in T:

type Writable<T> = {
    -readonly [P in keyof T]: T[P];
}

class HttpClient {
    private handler: any;

    readonly foo: any;

    get(): void {
      // ...
    }
}

 // Error: property 'handler' is missing in type 'Writable<HttpClient>'
 // but required in 'HttpClient'
const httpClient: HttpClient = {} as Writable<HttpClient>; 

Is there a way to get this working?

like image 362
Dirk Luijk Avatar asked Nov 22 '25 04:11

Dirk Luijk


1 Answers

A mapped type, such as Writable can't map over private fields (they are not part of what keyof returns). This is by design, after all a private field should not be accessible from outside.

Also if a class has a private field, an object literal (even if it contains the private field) can't by definition satisfy the type of the class.


 // Property 'handler' is private in type 'HttpClient' but not in type '{ handler: string; foo: string; get(): void; }'.
const httpClient: HttpClient = { // not assignable
  handler: "",
  foo: "",
  get () {}
}

Even another class with a private field with the same name can't satisfy the original class.

// Type '(Anonymous class)' is not assignable to type 'HttpClient'.
//   Types have separate declarations of a private property 'handler'.
const httpClient2: HttpClient = new class { // not assignable
  private handler: any
  foo: any
  get () {}
} 

The only way to make this work is if the private field is optional:

class HttpClient {
    private handler?: any;

    readonly foo: any;

    get(): void {
      // ...
    }
}

const httpClient: HttpClient = {
  foo: "",
  get () {}
}
console.log(httpClient instanceof HttpClient) // false 

Play

Also since an object with writable properties is assignable to a reference with a readonly property there is no need for Writable at all.

Note: Even though you can assign an object literal to the class it will not be an instance of the class, so httpClient instanceof HttpClient is false.

like image 105
Titian Cernicova-Dragomir Avatar answered Nov 23 '25 22:11

Titian Cernicova-Dragomir



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!