john_per
john_per

Reputation: 320

Threejs Geometry and TypeScript

I would like to write correct types for the Mesh Vertices and Faces.

In the first example, I create a new Mesh, and when I want to access Vertices and Faces from geometry, I get a few errors:

const material = new THREE.MeshLambertMaterial({color: 0x00ff00});
const geometry = new THREE.Geometry();
const newMesh = new THREE.Mesh(geometry, material);
scene.add(newMesh);

const { vertices, faces } = newMesh.geometry;
// Error: Property 'vertices' does not exist on type 'BufferGeometry | Geometry'
// Error: Property 'faces' does not exist on type 'Geometry | BufferGeometry'.

newMesh.geometry.colorsNeedUpdate = true;
// Error: Property 'colorsNeedUpdate' does not exist on type 'Geometry | BufferGeometry'.

In the second example, I get Mesh from the Scene, and then I get the following error:

const mesh = scene.getObjectByName('boxMesh');
const geometry = mesh.geometry; 
// Property 'geometry' does not exist on type 'Object3D'.

Upvotes: 2

Views: 4440

Answers (1)

brunnerh
brunnerh

Reputation: 185553

By accessing the geometry via the mesh (newMesh.geometry) you get the geometry typed like the geometry property on the Mesh class. Apparently the property supports two different types of geometry so you get a union: Geometry | BufferGeometry.

If you know exactly what type of geometry is used you can just assert the type of the property value:

const { vertices, faces } = <THREE.Geometry>newMesh.geometry;

If you do not know the type of geometry you need some conditional logic, e.g. using something like:

const geometry = newMesh.geometry;
if (geometry instanceof THREE.Geometry)
    // geometry will be typed as Geometry here
else
    // geometry will be typed as BufferGeometry here

In the second case you use getObjectByName which always returns objects of the most basic type Object3D. Here you also have to assert the type of the result accordingly.

// Assuming the thing named boxMesh is a Mesh...
// The <any> assertion prevents additional type errors.
const mesh = <THREE.Mesh><any>scene.getObjectByName('boxMesh');

Upvotes: 3

Related Questions