79190379

Date: 2024-11-14 20:54:40
Score: 1.5
Natty:
Report link

Solution suggested in the comments:

// gl-matrix
type vec3 = [number, number, number] | Float32Array;
type ReadonlyVec3 = readonly [number, number, number] | Float32Array;
// three.js
type Vector3 = {x:number, y:number, z:number}

interface Thing{
    setPosition(p:ReadonlyVec3): void
    getPosition():ReadonlyVec3
}

class ThreeJsThing implements Thing{
    private position:Vector3 = {x:0, y:0, z:0}
    setPosition(p:ReadonlyVec3){
        // actually this.position.set(p[0], p[1], p[2])
        this.position.x = p[0]
        this.position.y = p[1]
        this.position.z = p[2]
    }
    getPosition(){
        // actually return vec3.fromValues(...) as const
        return [
            this.position.x,
            this.position.y,
            this.position.z
        ] as const
    }
}

let thing = new ThreeJsThing()
let position = [1, 2, 3] as vec3
thing.setPosition(position)
console.log(thing.getPosition())
console.log(thing.getPosition()[1])
// position = thing.getPosition() // Type 'readonly [...]' is not assignable to type 'vec3'.
// thing.getPosition()[1] = 5 // Cannot assign to '1' because it is a read-only property.

Here is another solution that was posted by KLASANGUI, got downvoted into oblivion and then deleted. Use with caution, it probably opens a whole nother can of worms and blows up at three more places but I consider it absolutely valid and a beautiful JavaScript flex. It completely solves every problem I stated without syntactic sugar compromises.

// gl-matrix
type vec3 = [number, number, number] | Float32Array;
type ReadonlyVec3 = readonly [number, number, number] | Float32Array;
// three.js
type Vector3 = { x: number, y: number, z: number }

interface Thing {
    position: vec3
}

class ThreeJsThing implements Thing {
    #position: Vector3 = { x: 0, y: 0, z: 0 }

    set position(p: vec3) {
        this.#position.x = p[0]
        this.#position.y = p[1]
        this.#position.z = p[2]
    }

    get position() {
        let p = this.#position
        const accessor = {
            length: 3,
            set 0(x:number) { p.x = x },
            get 0() { return p.x },
            set 1(y:number) { p.y = y },
            get 1() { return p.y },
            set 2(z:number) { p.z = z },
            get 2() { return p.z }
        };
        Object.setPrototypeOf(accessor, Array.prototype);
        return accessor as vec3
    }
}

let thing = new ThreeJsThing()
let position = [1, 2, 3] as vec3
thing.position = position
thing.position[1] = 5
position = thing.position
console.log(position)
Reasons:
  • RegEx Blacklisted phrase (2): downvote
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: Mircode