Augmenting / Extending THREE types with TypeScript .d.ts

Hi all,

I am in the process of building a web application that uses Node and TypeScript with a lot of core functionality from THREE. So far so good, especially using DefinitelyTyped @types/three library!

However, something I keep getting stuck on is including files that have moved to the examples folder. For example, I am having a problem loading SVG’s because the TypeScript compiler can’t see SVGLoader in @types/three - there is no augment file for it. I am quite happy writing my own .d.ts files for these classes, but I can’t seem to extend THREE with my own file…

Here is my .d.ts (I’ve only exposed the SVGLoader methods I need for now):

import { LoadingManager, ShapePath } from "three";

declare module 'three' {
    namespace THREE {
        class SVGLoader {
            constructor(manager?: LoadingManager);
            load(url: string, onLoad?: (paths: ShapePath) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;
        }
    }
}

And how I would like to use it in my application .ts file:

import { SVGLoader } from ‘three’;

const svgLoader: SVGLoader = new SVGLoader();

My error is: Module …/node_modules/@types/three/index has no exported member ‘SVGLoader’.

Any help would be greatly appreciated.

I’m not familiar with typescript so I don’t know if this helps. But SVGLoader is no part of the library core. Instead, it’s part of the examples which means you don’t find the class in the default THREE namespace. You always have to include the file manually like in this demo:

https://threejs.org/examples/webgl_loader_svg.html

Thanks for the quick response. I think this issue might be more concerned around the way I am currently attempting to import ThreeJS example files into TypeScript using Webpack. After a lot of Googling I’ve only found a handful of StackOverflow answers where this is tackled. This one seems to give the clearest answer:

Though I am having difficulties implementing it myself - I still get errors such as “SVGLoader not found” on compilation, or after a bit of fiddling, I get a similar error at runtime. As this project has a tight deadline I have to leave this question as an ongoing investigation. If I manage to figure out a step-by-step process for getting it working I will post up a solution.

1 Like

Hi Andy,

Did you found any solution for that?

I’m having the same problems as you.

Hey,

No I didn’t. I’ve resorted to pngs sadly. I had to sack off this idea in the name of deadlines.

There’s a bit of mismatch between DefinitelyTyped’s ThreeJS definitions and what is in the latest ThreeJS library but I think it will be at a workaround situation unless someone has time to go through the examples folder and write definitions for those. On the plus side the DefinitelyTypes community is pretty good at merge requests. I had mine pulled in less than 3 days.

One workaround might be to use JS in the instance where you will be relying on this, and save TS for more robust projects.

Is it not possible to just make your own types for that specific loader?

If a project is robust rather depends on the own discipline :stuck_out_tongue:

I’m using an old three.d.ts declaration file, so not sure if this will still work, but I created a second file in types/global.d.ts where I manually write all my extra declarations that are not part of the core library.

When I need to add a new class to the THREE namespace, I simply follow this structure:

declare namespace THREE{
	export class DecalGeometry extends Geometry{
		constructor(meshToIntersect: Geometry, position: Vector3, direction: Vector3, dimensions: Vector3, check?: Vector3);
	}
}

Then you can write additional method and property definitions inside that class. Hope this method works for you as well!

2 Likes

Yeah it is possible to make your own types for that loader, you just need to essential type out a definitions file. I considered this as a viable option. The only problem I’ve found is that sometimes that class can rely on other classes that will also need a definitions file and then you end up writing a whole load of them. As I said in my original post, I just didn’t have time to do that in this scenario, but will certainly look to do it (and share it) in the future.

Very true. Apologies for my inflammatory comment.

Hi Andy, I found a solution, using three-full

Please try and share your doubts

1 Like

Thanks for sharing this repo. It’s pretty comprehensive, and I’m glad that it exists! It doesn’t quite solve the issue of TypeScript definitions as there is no definitions for this repo, but as stated earlier that’s just a question of roll your own :slight_smile:

1 Like

Hi Daniel
I am using this three-full package in my angular project. But when I use its FBXLoader it gives an error while loading a fbx model

TypeError: child.material.clone is not a function
at Three.es.js:60764
at Mesh.traverse (Three.es.js:3918)
at Group.traverse (Three.es.js:3924)
at FBXTreeParser.setupMorphMaterials (Three.es.js:60742)
at FBXTreeParser.parseScene (Three.es.js:60174)
at FBXTreeParser.parse (Three.es.js:59479)
at FBXLoader.parse (Three.es.js:59452)
at Object.onLoad (Three.es.js:59398)
at XMLHttpRequest. (Three.es.js:21917)
at ZoneDelegate.push…/node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)

Any Idea about this?

Hi, sorry for the delay.
I have no idea… :pensive:

I figured it out, it has a bag so I converted the official fbx loader js file from THREEJS to a node module and now it works