2

I have a Node.js project that uses Typescript and Three.js. To import modules, I use the commonjs syntax, which I configured via

{
  "compilerOptions": {
    "module": "commonjs"
  }
}

in my tsconfig.json. I downloaded Three.js via NPM have a typescript file like this:

const THREE = require('three');
const scene = new THREE.Scene();

which compiles fine, but I do not get any autocomplete. I don't think this specific to the editor used, as both Visual Studio Code as well as Neovim with YouCompleteMe don't work. Both work if I use the ES6 module syntax:

import * as THREE from 'node_modules/three/src/Three';
const scene = new THREE.Scene();

Here however I cannot get it to work without giving the actual path to the library (which is a problem later on when using webpack). What did I forget to configure to get autocomplete (or the ES6 syntax without explicitly defining the path, at this point I am fine with both solutions)?

EDIT

As mentioned in the comments to accepted answer, I was not able to find my mistake, but found a working solution while trying to create a minimal working project. So I will post this here, in case it might help someone else. If you have the same problem, please still read the answer, as it is correct.

My source file (in src/main.ts):

import * as THREE from 'three';
const scene = new THREE.Scene();

package.json (with webpack to test if the library can be resolved there):

{
  "devDependencies": {
    "@types/node": "^12.0.4",
    "three": "^0.105.2",
    "ts-loader": "^6.0.2",
    "typescript": "^3.5.1",
    "webpack": "^4.32.2",
    "webpack-cli": "^3.3.2"
  }
}

tsconfig.json:

{
  "compilerOptions": {
      "baseUrl": ".",
      "paths": { "*": ["types/*"] },
    "target": "es6",
    "module": "es6",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "sourceMap": true
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules/"
  ]
}

webpack.config.js:

const path = require('path');

module.exports = {
    entry: './src/main.ts',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    resolve: {
        extensions: [ '.ts', '.js' ]
    },
    module: {
        rules : [
            { test: /\.ts$/, use: [ 'ts-loader' ], exclude: /node_modules/ }
        ]
    }
};

1 Answer 1

5

What version of three is installed in your package.json file? Make sure it's 0.101 or later, since that's when TypeScript support began. I recommend you use the latest (105 as of this writing), since it gets updated definition files on each release.

Then, in your .ts files, you can import it with:

import * as THREE from "three";

// After importing, THREE is available for auto-complete.
var lala = new THREE.WebGLRenderer();

Edit:

You might need to perform path-mapping in your .tsconfig file to force the compiler to find the correct module address. I've never had to do this, but the Typescript documentation suggests something like this:

{
  "compilerOptions": {
    "baseUrl": ".", // This must be specified if "paths" is.
    "paths": {
      "three": ["node_modules/three/src/Three"] // relative to "baseUrl"
    }
  }
}

Update r126

As of revision r126, Three.js has moved Typescript declaration files to a separate repository. If you're using r126 or later, you'll have to run npm install @types/three as a second step. Make sure you install the version of @types/three that targets your version of Three.js. For example:

"three": "0.129.0",
"@types/three": "^0.129.1",
Sign up to request clarification or add additional context in comments.

3 Comments

I already use Three.js version 0.105.2, but the syntax suggested by you (ES6 with just 'three') does not work for me ("Cannot find module 'three'")
That's strange. I edited my answer to provide an alternative path-mapping method in case your compiler needs a little push to find the module. It depends on your folder hierarchy, but typically you'd have .tsconfig and node_modules/ folder in the same location. You might run into problems if they're at different folder depths.
Thanks for your answer. At first, it did not work for me, so I tried to create a minimal project to post for you to reproduce the problem. In this minimal example, your first solution already works and I do not have to set the path to Three.js explicitly, even with the ES6 syntax. Apparently I had messed up my configuration somewhere. I will still post the (now working) minimal example, in case someone might need it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.