TS: mesh.material type?
See original GitHub issueDescription of the problem
https://github.com/mrdoob/three.js/blob/dev/src/objects/Mesh.d.ts#L16
The type of property material
on the Mesh
class is Material | Material[]
.
I run into an issue when i use:
const myMesh = new Mesh( someGeometry, new MeshBasicMaterial())
myMesh.material.map = foo //error
The workaround for me is:
const someMaterial = new MeshBasicMaterial()
const myMesh = new Mesh(someGeometry, someMaterial)
someMaterial.map = foo // no error, because the interface is from MeshBasicMaterial
However, the code can end up being somewhat ugly. I tend to end up with something like:
this.material // :Material
this._typedMaterial // ShaderMaterial
Prettier goes crazy when i try to cast it and i end up with something like:
;(this.material as MeshBasicMaterial).map = foo
If i have a few lines to set, i need to do this on each, hence storing it in a variable with the proper type feels less awkward.
Even something that is generic and common for all Material
sub classes fails because of the | Material[]
such as dephTest
.
I was wondering if something involving generics could be applied here, ie:
const myMesh = new Mesh<MeshBasicMaterial>(someGeometry, new MeshBasicMaterial)
myMesh.map = foo //no error because Mesh would use <T>
I’m not sure what the exact syntax for this could be, and if <T>
can be limited to a subclass of Material
, but the Material
interface seems somewhat awkward since it’s sort of a utility class, everything we end up using extends from it. But even the class being generic is not that much of an issue, the possibility of the type being an array breaks it more.
Is this an issue, and if it is, what would be the solution? Is there a more elegant typescript approach where the property could be just inferred from the type of material passed?
Three.js version
- Dev
- r116
Browser
- All of them
- Chrome
- Firefox
- Internet Explorer
OS
- All of them
- Windows
- macOS
- Linux
- Android
- iOS
Issue Analytics
- State:
- Created 3 years ago
- Comments:12 (7 by maintainers)
Top GitHub Comments
I’m not aware of anything like that, except generics.
I think you’re on the right track with generics, see https://github.com/mrdoob/three.js/issues/19072 and https://github.com/mrdoob/three.js/pull/18720. Probably this can be solved with some changes to the type definitions, although they’re somewhat complex changes so I’d hope we can get some more experienced TypeScript users to take that on. That
.material
might be an array seems like the trickiest part.^Yes, I think that’s fine. If the user is strict with their own types (which is the whole point of TS) the compiler will know that
mesh.geometry
is a BufferGeometry and the code will stay clean. It really only becomes an issue for developers writing abstractions that must accept anything, in which case the required checks just become uglier, as APIs that deal with loose input in TS generally do. BecauseGeometry
is deprecated, that problem will go away.