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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With