Skip to content

Type checking

_Shortman edited this page Sep 29, 2025 · 2 revisions

This page documents how to set up type checking for your dev environment to assist with organisation and spotting errors.

Setup

You can optionally type-check your script against ProbeJS scripts by doing the following:

  • Add ProbeJS to the pack:
    https://www.curseforge.com/minecraft/mc-mods/probejs/files/4365861
  • Launch Minecraft
  • For best possible dump:
    • /kubejs reload client_scripts
    • /kubejs reload server_scripts
    • /kubejs reload startup_scripts
    • Try to sleep in a bed
    • Right-click a block with an item
    • Left-click a block with an item
  • Do /probejs dump
  • Typings should appear in:
<instance>/minecraft/kubejs/probe/generated

Because ProbeJS exports typings for synthetic methods (for example generated by Mixin) that contain dashes in names, generated globals.d.ts is broken because in JavaScript methods can't have dashes in names.

  • Open up globals.d.ts in a text editor that supports replacing by regular expression. Instructions will assume VS Code or similar editor.
  • Click on the "Use regular expression" button.
  • Replace all (?<!")((?=\S*['-])(?:[a-zA-Z$\d_'-]+))(?!")(?=\() with "$1".
  • There should be no more syntax errors.

Also, because ProbeJS tries and fails to type global:

  • Open up constants.d.ts.
  • Remove or comment out the line starting with declare const global: ....
  • Now global should be properly inferred.

Then:

  • Copy over the probe folder from the Minecraft instance to the repository. probe is in .gitignore, so it won't be included in your commits.
  • Use the following command to stop changes to kubejs/jsconfig.json from being committed:
git update-index --assume-unchanged kubejs/jsconfig.json

(Later on, if you want to change something else than type-checking, use the following command.)

git update-index --no-assume-unchanged kubejs/jsconfig.json
  • In kubejs/jsconfig.json, change the checkJs field from false to true.

And here you go! Now every JavaScript file will be type-checked against types from ProbeJS and custom declarations in this repository!

(function myCoolScript() {
  let a = 5;
  a = "string";
  // ^ Error: Type 'string' is not assignable to type 'number'.
});

Using types

TypeScript can infer basic types from usage, but in many cases you will need to explicitly set the type of item using JSDoc comments.

Useful links:

Some basic syntax that is commonly used throughout the codebase:

Setting a type of the variable

/** @type {Internal.IngredientJS_[]} */
let HIDDEN_ITEMS = [
  "ae2:silicon",
  "extended_drawers:t1_upgrade",
  "extended_drawers:t2_upgrade",
  //...
]
// Now HIDDEN_ITEMS is an array of anything that is Internal.IngredientJS_.

Defining types

Types
/** @typedef {"create:blaze_burner" | "createaddition:liquid_blaze_burner"} Burner */

// This is equivalent to the following TypeScript syntax:
type Burner = "create:blaze_burner" | "createaddition:liquid_blaze_burner"

// Now the type can be used in the script:
/** @type {Burner} */
let burner = "create:blaze_burner"
// Can only hold literal strings defined in the "Burner" type
Interfaces

Interfaces declare the shape of an object. They can be used as a type of variable or a constant.

/**
 * @typedef CrushingRecipeToBecomeGrinding
 * @property {object} input
 * @property {Special.Item} input.item
 * @property {object} output
 * @property {Special.Item} output.item
 * @property {number} output.count
 * @property {number} [time]
 * @property {number} [power]
 */
// Properties in square brackets are considered optional.

// This is equivalent to the following TypeScript syntax:
interface CrushingRecipeToBecomeGrinding {
  input: { item: Special.Item };
  output: { item: Special.Item; count: number };
  time?: number;
  power?: number;
}

// Now the type can be used in the script:

/** @type {CrushingRecipeToBecomeGrinding[]} */
const crushingRecipesToBecomeGrinding = [
  //...
]

Declaring a list immutable

// @satisfies {string[]} ensures that the array is an array of strings without changing the array's type.
// @type {const} declares that the array won't ever change.
// Thanks to that, TypeScript can check for validity of strings in template literals more effectively.
// Mind the round brackets!
/** @satisfies {string[]} */
const names = /** @type {const} */ ([
  "helmet",
  "chestplate",
  "leggings",
  "boots",
  "sword",
  "pickaxe",
  "shovel",
  "axe",
  "hoe",
]);

Common types

  • For items used in KubeJS functions, use types:
    • Special.Item - accepts only strings corresponding to items,
    • Internal.ItemStackJS_ - accepts Items and other strings corresponding to items.
    • Internal.IngredientJS_ - a huge type that encompasses most things that can be ingredients.

Prefer using Item.of("minecraft:apple", 5) instead of 5x minecraft:apple - the latter will throw an error when type checked.

  • For fluids used in KubeJS functions, use types:
    • Special.Fluid - accepts only strings corresponding to fluids,
    • {fluid: Special.Fluid, amount: number} - accepts any object that conforms to this type.
    • Internal.IngredientJS_ - a huge type that encompasses most things that can be ingredients.

Recommended VSCod(e/ium) settings

  • TypeScript › Tsserver › Experimental: Enable Project Diagnostics: Enabled.

With this option, the entire project will be type-checked instead of just open files.

  • JavaScript › Inlay Hints › Function Like Return Types: Enabled.
  • JavaScript › Inlay Hints › Parameter Types: Enabled.
  • JavaScript › Inlay Hints › Property Declaration Types: Enabled.
  • JavaScript › Inlay Hints › Variable Types: Enabled.

These options will display hints based on inferred variable types.

Clone this wiki locally