Skip to content

TypeScript

You may want to use TypeScript when developing your React Three Fiber applications.

TypeScript is a tool that you can use when developing, to help you make sure all your code is type safe. I.e., if you need to pass an integer to a function, but you write it as a string instead, then the TypeScript compiler will notify you while developing.

Using TypeScript is optional, and many syntax issues can already be found if using ESLint as described at ESLint.

Using TypeScript in a React application requires some extra considerations since types are not automatically inferred when using some hooks, such as the useRef hook.

So to follow this small tutorial, use the courses Leva branch.

git clone https://github.com/Sean-Bradley/React-Three-Fiber-Boilerplate.git
cd React-Three-Fiber-Boilerplate
git checkout leva
npm install
npm start

Later, you can experiment with a copy of your own project, provided that you are using react-scripts or R3F-pack to build it.

Install Latest R3F-Pack

Note

If your project is already using R3F-pack, then you can skip this next step.

Ensure that your project is using the latest R3F-pack bundler and not react-scripts

In your own project, check the start and build commands in your package.jsonscripts node to see which one.

If it is using react-scripts, then uninstall it.

npm uninstall react-scripts

Next, install the latest R3F-Pack

npm install r3f-pack@latest --save-dev

And make sure your package.jsonscripts node is using the r3f-pack command and not react-scripts

{
    ...
    "scripts": {
-       "start": "react-scripts start",
+       "start": "r3f-pack start",
-       "build": "react-scripts build",
+       "build": "r3f-pack build"
    },
    ...
}

Rename file extensions from jsx to tsx

Rename files with the jsx extension, to use the tsx extension.

App.jsx --> App.tsx
index.jsx --> index.tsx
Polyhedron.jsx --> Polyhedron.tsx

The files may now show some errors and warnings when viewed in the IDE. We will fix those.

Rename

Install TypeScript

Press Ctrl C a few times to stop the development web server and execute,

npm install typescript --save-dev

Add a tsconfig.json

Add a tsconfig.json to your projects root folder.

Copy/paste the contents below into it and save.

{
  "include": ["./src/**/*"],
  "compilerOptions": {
    "strict": true,
    "esModuleInterop": true,
    "lib": ["dom", "es2015"],
    "jsx": "react-jsx"
  }
}

tsconfig.json

Install Type Definitions

The IDE will read your code and try to match the types to it. You can tell it which definition files to use.

npm install @types/node --save-dev
npm install @types/react --save-dev
npm install @types/react-dom --save-dev
npm install @types/three --save-dev

After installing type definitions, it can take some time for the IDE to catch up. Try pressing F1, and select Restart TS Server.

Also note that you should try to match the versions of the types with the library installed.

E.g., If you are using Three@0.157.0 then install the closest @types/three version such as,

npm install @types/three@0.157.0 --save-dev

Note

Since the type definitions are developed separately from the main library, the latest version numbers won't always be in sync. Just try to match the closest number that you can, and you may not experience any issues unless you are using some part of the library where the method signature was recently changed.

Add types to index.tsx

In index.tsx, the IDE is unsure what type is being returned from the document.getElementById method. We can cast the type as a HTMLDivElement.

Change the createRoot line from,

createRoot(document.getElementById('root')).render(

to

createRoot(document.getElementById('root') as HTMLDivElement).render(

When working with TypeScript, you often need to figure out the correct type of variable, or the value a method returns.

Sometimes you might get stuck trying to figure out the best type to use. In that case, you can cast as any.

createRoot(document.getElementById('root') as any).render(

Or, you can add the directive // @ts-ignore before the line containing the error.

// @ts-ignore
createRoot(document.getElementById('root')).render(

Add types to Polyhedron.tsx

There are several problems in this file, lets look at Binding element 'polyhedron' implicitly has an 'any' type

The Polyhedron function is using destructuring assignment and a rest (...) operator.

Since when creating the Polyhedron, which is based on a THREE.Mesh, but with some extra custom attributes, I have chosen to create an interface named IPolyhedron which extends from the R3F MeshProps since the function returns a <mesh>

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import { MeshProps } from '@react-three/fiber'
import { useRef, useState } from 'react'

interface IPolyhedron extends MeshProps {
  polyhedron: THREE.BufferGeometry[]
  color: THREE.Color | String
}

export default function Polyhedron({
  polyhedron,
  color,
  ...props
}: IPolyhedron) {
  const ref = useRef<THREE.Mesh>(null!)
  const [count, setCount] = useState(2)

  console.log(polyhedron[count].uuid)

  return (
    <mesh
      {...props}
      ref={ref}
      onPointerDown={() => {
        setCount((count + 1) % 3)
      }}
      geometry={polyhedron[count]}>
      <meshBasicMaterial color={color as THREE.Color} wireframe />
    </mesh>
  )
}

Also, since there is a useRef hook pointing to a mesh JSX element, I have declared it as,

const ref = useRef<THREE.Mesh>(null!)

Also, I needed to cast color as THREE.Color to avoid a problem in App.tsx where it passed the value as a string, and Leva could pass as a color, but the JSX in Polyhedron.tsx requires it to be a THREE.Color.

// line 20 App.tsx
color: {
  value: 'lime'
}
// line 6 Polyhedron.tsx either THREE.Color or String
color: THREE.Color | String
// line 27 Polyhedron.tsx
<meshBasicMaterial color={color as THREE.Color} wireframe />

npm start

All problems should now be solved, we can run,

npm start

Working Example

<>
Leva (TypeScript version) sbedit.net GitHub
Materials (TypeScript version) sbedit.net GitHub
GLTFJSX (TypeScript version) sbedit.net GitHub
Using with TypeScript Pmdrns.docs

GitHub Branches

These 3 branches below show some variation in how I solved adding Types to the code.

leva-typescript

git clone https://github.com/Sean-Bradley/React-Three-Fiber-Boilerplate.git
cd React-Three-Fiber-Boilerplate
git checkout leva-typescript
npm install
npm start

materials-typescript

git clone https://github.com/Sean-Bradley/React-Three-Fiber-Boilerplate.git
cd React-Three-Fiber-Boilerplate
git checkout materials-typescript
npm install
npm start

useGLTF-typescript

git clone https://github.com/Sean-Bradley/React-Three-Fiber-Boilerplate.git
cd React-Three-Fiber-Boilerplate
git checkout useGLTF-typescript
npm install
npm start

Troubleshooting

Error 'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.

Ensure you have a tsconfig.json and that you have installed the type definitions for both React and React-dom.

npm install @types/react --save-dev
npm install @types/react-dom --save-dev

If using VSCode, then you can press F1 and select Restart TS Server to re-scan the type definitions.

Error : TypeError: THREE.Vector3 is not a constructor

I have seen this error when using react-scripts@5.0.1 with typescript@4.x.x and @react-three/drei.

Upgrade your package.json to reference the latest TypeScript.

npm install typescript@latest --save-dev

Now you have a choice here to instead upgrade your project to use R3F-pack, or you can continue to use react-scripts to start and build your project.

If you choose to continue to use react-scripts, then you will need to add an overrides section to your package.json that matches the version of TypeScript that was just installed.

//  ... existing package.json
    "typescript": "^5.1.3"
  },
  "overrides": {
    "typescript": "^5.1.3"
  }
}

Error : npm ERR! While resolving: react-scripts@5.0.1

When executing npm install you see the error,

npm install
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: react-scripts@5.0.1
npm ERR! Found: typescript@5.x.x

You are using react-scripts and have TypeScript 5 or above installed, but not yet added the overrides node to your package.json

See TypeError: THREE.Vector3 is not a constructor

Comments