How to Use Matter.js with TypeScript

Yes, Matter.js can be used with TypeScript seamlessly. While the 2D physics engine is originally written in standard JavaScript, full type definitions are available through the DefinitelyTyped repository. This guide explains how to install the required packages, configure your project, and implement a basic physics simulation using TypeScript’s static typing and autocompletion features.

Installing Matter.js and Types

To begin, install the core matter-js library alongside its official TypeScript declaration package as a development dependency:

npm install matter-js
npm install --save-dev @types/matter-js

Ensure your tsconfig.json contains "moduleResolution": "node" and "esModuleInterop": true to allow smooth importing of CommonJS modules.

Basic Setup Example

You can import either individual modules or the entire Matter namespace. Here is how to initialize an engine, a renderer, and basic rigid bodies in a TypeScript file:

import { Engine, Render, Runner, Bodies, Composite } from 'matter-js';

// Create an engine instance
const engine = Engine.create();
const world = engine.world;

// Create a renderer
const render = Render.create({
  element: document.body,
  engine: engine,
  options: {
    width: 800,
    height: 600,
    wireframes: false
  }
});

Render.run(render);

// Create a runner
const runner = Runner.create();
Runner.run(runner, engine);

// Add rigid bodies with typed options
const boxA = Bodies.rectangle(400, 200, 80, 80);
const boxB = Bodies.rectangle(450, 50, 80, 80);
const ground = Bodies.rectangle(400, 590, 810, 60, { isStatic: true });

Composite.add(world, [boxA, boxB, ground]);

Leveraging TypeScript Features

Using Matter.js with TypeScript provides several development advantages:

  1. Configuration Autocompletion: When creating bodies via Bodies.rectangle() or Bodies.circle(), passing the options argument exposes the IBodyDefinition interface. This provides instant IDE feedback for properties such as restitution, friction, density, and collisionFilter.
  2. Event Typing: Matter.js event listeners provide typed payload objects. When listening for collision events, events like collisionStart pass an IEventCollision<Engine> parameter, helping you safely access pairs and body references:
import { Events, IEventCollision } from 'matter-js';

Events.on(engine, 'collisionStart', (event: IEventCollision<Engine>) => {
  event.pairs.forEach((pair) => {
    console.log('Collision between:', pair.bodyA.label, pair.bodyB.label);
  });
});
  1. DOM Element Safety: Passing container elements to Render.create() enforces standard HTML element types, reducing runtime null errors when binding the simulation canvas to the DOM.