After looking at all the codes of babylon.js,
I found that the DeepImmutable
type exists just to support Immutable for the container type related to math(e.g Vector3).
But DeepImmutable
is actually not fully ensure a immutable. Because a method exists to modify self.
for example:
const vec: DeepImmutable<Vector3> = new Vector3(); // create immutable vector3
vec.set(1, 2, 3); // vec modified by method
To solve this problem. I think it is desirable to implement Immutable by creating a separate Readonly interface.
This is the ideal code I think:
export type ImmutConvertable<T = any> = T & {
freeze(): T;
};
export type Immutable<T extends ImmutConvertable> =
T extends ImmutConvertable<infer U>
? U
: never;
/*
* Ensure complete Readonly
* by putting only the members you want to expose into the interface.
*/
interface ReadonlyVector3 {
readonly x: number;
readonly y: number;
readonly z: number;
}
class Vector3 implements ImmutConvertable<ReadonlyVector3> {
public x: number;
public y: number;
public z: number;
public constructor(x: number, y: number, z: number) {
this.x = x;
this.y = y;
this.z = z;
}
public freeze(): ReadonlyVector3 {
return Object.freeze(this);
}
public set(x: number, y: number, z: number): Vector3 {
this.x = x;
this.y = y;
this.z = z;
return this;
}
public copy(other: Immutable<Vector3>): Vector3 {
this.x = other.x;
this.y = other.y;
this.z = other.z;
return this;
}
}
type A = Immutable<Vector3>;
// ^---type A is evaluated to `ReadonlyVector3`
If I receive a positive response to this design change, I can implement it.