Wiki 9Minecraft Wiki 9Minecraft

TypeScript Setup for Bedrock Scripting API

Configure a TypeScript build pipeline with official @minecraft type definitions for behavior pack scripts.

5Sections
4Code examples
4Known errors

Minecraft Bedrock's Scripting API runs standard JavaScript inside the QuickJS engine, meaning the game cannot execute TypeScript (.ts) files directly. Using TypeScript in your workflow lets you catch API signature mismatches, undefined properties, and misspelled event names in your editor before loading a world. You write your logic in TypeScript outside the game directory and compile it down to standard ES2020 JavaScript inside your Behavior Pack's scripts folder.

How TypeScript Works with Bedrock

When Minecraft loads a Behavior Pack with a script module, it looks at the entry file specified in your manifest.json—almost always a .js file inside BP/scripts/. Because the engine has no built-in TypeScript compiler, you must keep your .ts source files in a separate workspace folder and run a build step to output .js files into the Behavior Pack.

Mojang publishes official type definition packages to the npm registry corresponding to each scripting module. These packages contain zero runtime code; they only provide interfaces, class declarations, and JSDoc comments that your code editor and the TypeScript compiler use to validate your script against a specific Minecraft version.

Project Structure and Dependencies

A clean TypeScript add-on project separates source files from the final pack files. Keep your package.json, tsconfig.json, and a src/ directory at the root of your workspace, outside the BP/ folder so you do not accidentally bundle node_modules into your .mcpack archive.

Install the typescript compiler alongside the official Minecraft type packages. The version number in your package.json must match the version declared in your Behavior Pack's manifest dependencies.

npm PackageWhat it providesManifest Match
@minecraft/serverCore world, entity, block, item, and system event typesMust match module_name "@minecraft/server" version in manifest.json
@minecraft/server-uiActionFormData, ModalFormData, and MessageFormData typesMust match module_name "@minecraft/server-ui" version in manifest.json
@minecraft/vanilla-dataEnums for vanilla block, item, entity, and effect identifiersBundled by third-party bundlers only; not a native game module
package.json
{
  "name": "my-bedrock-addon",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w"
  },
  "devDependencies": {
    "@minecraft/server": "1.14.0",
    "@minecraft/server-ui": "1.3.0",
    "typescript": "^5.5.0"
  }
}

Configuring tsconfig.json

Your tsconfig.json tells the TypeScript compiler how to translate your source code so that Bedrock's QuickJS runtime can understand it. Set target and module to ES2020 or ES2022, and set moduleResolution to node so the compiler locates the @minecraft packages inside node_modules.

Point rootDir to your TypeScript source directory and outDir to the scripts folder inside your Behavior Pack. When you run the build command, TypeScript mirrors the folder structure of src/ directly into BP/scripts/ as .js files.

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ES2020",
    "moduleResolution": "node",
    "lib": ["ES2020"],
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "rootDir": "./src",
    "outDir": "./BP/scripts"
  },
  "include": ["src/**/*"]
}

Linking the Compiled Output in manifest.json

Your Behavior Pack's manifest.json knows nothing about TypeScript. Its script module entry must point to the compiled .js file inside BP/scripts/, not the original .ts file in src/.

Make sure every @minecraft module you import in your TypeScript code is also listed in the dependencies array of manifest.json with the exact same version number installed via npm.

BP/manifest.json
{
  "format_version": 2,
  "header": {
    "name": "TypeScript Demo Pack",
    "description": "Behavior pack using compiled TypeScript",
    "uuid": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d",
    "version": [1, 0, 0],
    "min_engine_version": [1, 21, 0]
  },
  "modules": [
    {
      "description": "Script Module",
      "type": "script",
      "language": "javascript",
      "uuid": "f5e4d3c2-b1a0-4f5e-9d8c-7b6a5f4e3d2c",
      "version": [1, 0, 0],
      "entry": "scripts/main.js"
    }
  ],
  "dependencies": [
    {
      "module_name": "@minecraft/server",
      "version": "1.14.0"
    },
    {
      "module_name": "@minecraft/server-ui",
      "version": "1.3.0"
    }
  ]
}

Writing Typed Script Code

Inside your src/ folder, import classes and interfaces alongside runtime objects like world and system. Type annotations let you safely narrow down component types and event payloads without guessing property names.

Notice that when you import your own helper files using relative paths in ES2020 modules, you must write the .js extension in the import statement even though you are editing a .ts file. TypeScript does not rewrite file extensions inside import strings during compilation, and Bedrock's module loader requires explicit .js extensions to locate local files.

src/main.ts
import {
  world,
  PlayerBreakBlockAfterEvent,
  EntityInventoryComponent,
  ItemStack
} from "@minecraft/server";

world.afterEvents.playerBreakBlock.subscribe((event: PlayerBreakBlockAfterEvent) => {
  const { player, brokenBlockPermutation } = event;

  if (brokenBlockPermutation.type.id === "minecraft:diamond_ore") {
    const inventory = player.getComponent(
      EntityInventoryComponent.componentId
    ) as EntityInventoryComponent | undefined;

    if (inventory && inventory.container) {
      const bonusItem = new ItemStack("minecraft:emerald", 1);
      inventory.container.addItem(bonusItem);
      player.sendMessage("You found a bonus emerald in the diamond ore!");
    }
  }
});

Which versions this applies to

Applies to all modern Bedrock versions supporting the Scripting API (1.19.50+). Stable npm versions (such as 1.14.0) require no experimental toggles. Installing packages with a '-beta' suffix (for example, '1.15.0-beta.1.21.30-stable') requires enabling the Beta APIs experimental toggle in the world settings.

When it does not work

What you seeWhyThe fix
Content Log Error: [Scripting][error]-ReferenceError: Cannot find module './utils' from 'scripts/main.js'You wrote `import { myHelper } from './utils'` in your TypeScript file without a file extension. TypeScript leaves import specifiers untouched, and Bedrock's module loader requires the full `.js` extension.Change the import in your `.ts` file to `import { myHelper } from './utils.js'`. TypeScript understands that `.js` refers to `./utils.ts` during compilation.
Content Log Error: [Scripting][error]-SyntaxError: Unexpected token ':' in scripts/main.tsYour `manifest.json` entry points to a `.ts` file, or you placed raw TypeScript files inside `BP/scripts/`. The game engine tried to parse TypeScript type annotations as standard JavaScript.Move `.ts` files outside the Behavior Pack into `src/`, run `npx tsc` to compile them into `BP/scripts/main.js`, and ensure `manifest.json` has `"entry": "scripts/main.js"`.
Code compiles with zero TypeScript errors, but in-game the Content Log throws: TypeError: not a functionThe `@minecraft/server` version installed in `package.json` is newer than the version declared in `BP/manifest.json` (or you installed a `-beta` package in npm while using a stable version in the manifest).Align the version strings in both `package.json` and `BP/manifest.json`. If using a `-beta` version in both, enable the Beta APIs toggle on the world.
Content Log Error: [Scripting][error]-ReferenceError: Cannot find module '@minecraft/vanilla-data'You imported enums from `@minecraft/vanilla-data` using standard `tsc` compilation. Unlike `@minecraft/server`, `@minecraft/vanilla-data` is not built into the game client.Either use a bundler like esbuild or Rollup to inline third-party npm packages into your output `.js` files, or replace the enum imports with plain string literals like `"minecraft:stone"`.

Reference, straight from the game files

Read out of the game itself, so the ids match the version you are building for.