npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

typed-factorio

v3.9.0

Published

Featureful typescript definitions for the Factorio modding api.

Downloads

653

Readme

NPM Version Factorio version

Typed Factorio

Complete and featureful typescript definitions for the Factorio modding lua API, for use with TypescriptToLua.

This project aims to provide type definitions are as complete as possible. The generator uses both the Factorio api docs JSON and manually defined additions.

Installation

To use in your TypescriptToLua project:

  1. Install this package: npm install typed-factorio

    • Note: When types are updated for a new factorio version, you will need to update this package.
  2. Add types for the stages used to tsconfig.json > compilerOptions > types. The available stages are "typed-factorio/settings", "typed-factorio/prototype", and "typed-factorio/runtime".

Example:

// in tsconfig.json
{
  "compilerOptions": {
+    "types": [ "typed-factorio/runtime" ]
  }
}

The stages used will select the global variables defined. You can include multiple stages, but there are some caveats. See Using multiple stages in the same project for more info.

Usage notes

Here are some notes on using the types:

Types for other stages

No matter which stage(s) are selected, type definitions for all stages are available in the modules "factorio:settings", "factorio:prototype", and "factorio:runtime":

import { BoolSettingDefinition } from "factorio:settings"
import { ItemPrototype } from "factorio:prototype"
import { LuaEntity } from "factorio:runtime"

You can also include just "typed-factorio" in your types field. This will include only global variables available to all stages.

data.extend() types

In the settings and prototype stages, the data global variable is available.

For performance reasons, data.extend() is by default loosely typed. To get full type checking, you can use specific types in one of the following ways:

// Use `satisfies` to check types:
data.extend([
  {
    type: "ammo-category",
    name: "foo",
  } satisfies AmmoCategory,
  {
    type: "item",
    name: "bar",
    // ...other fields
  } satisfies ItemPrototype,
])

// List types as a type argument to `extend`:
data.extend<AmmoCategory | ItemPrototype>([
  {
    type: "ammo-category",
    name: "foo",
  },
  {
    type: "item",
    name: "bar",
    // ...other fields
  },
])

// Use types on separate variables:
const fooCategory: AmmoCategory = {
  /* ... */
}
const barItem: ItemPrototype = {
  /* ... */
}
data.extend([fooCategory, barItem])

Factorio lualib modules

There are types for the following Factorio lualib modules:

  • util
  • mod-gui

These can be imported as modules:

import * as util from "util"

const foo = util.copy(bar)

If you wish to see types for more lualib modules, feel free to open an issue or pull request.

The storage table

The storage table (in the runtime stage) can have any shape, so it is not defined here. Instead, you can define it yourself:

  • Add declare const storage: <Your type> in a .d.ts file. Make sure this file is included by your tsconfig!
  • Add declare global { const storage: <Your type> } in a .ts file included in your project.
  • Add declare const storage: {...} to each file where needed. This way, you can define only properties that each file specifically uses.

Using multiple loading stages in the same project

Every Factorio loading stage declares different global variables. To add types for multiple Factorio stages, you have a few options:

  1. Add multiple stages to the "types" field, e.g. "types": ["typed-factorio/prototype", "typed-factorio/runtime"]. This will define global variables for all stages selected. With this option, take care that you only use global variables available in the stages the code is run.
  2. Add only the runtime stage, then manually declare other global variables in files that use them. There are types in "factorio:common" to allow this:
    // -- For the prototype stage --
    import { PrototypeData, ActiveMods, FeatureFlags } from "factorio:common"
    declare const data: PrototypeData
    declare const mods: ActiveMods
    declare const feature_flags: FeatureFlags
    // The `settings` global variable is already declared in the runtime stage.
    // However, in the prototype stage _only_ `settings.startup` are available.
    // -- For the settings stage --
    import { SettingsData, ActiveMods, FeatureFlags } from "factorio:common"
    declare const data: SettingsData
    declare const mods: ActiveMods
    declare const feature_flags: FeatureFlags
  3. Use a separate tsconfig.json for each stage. In each tsconfig.json, add only files in that stage to the "include" field, e.g. include: ["src/control.ts"] for the runtime stage. However, this means you need to run tstl separately for each stage, and files shared by multiple stages will be compiled multiple times.

Type features

Here is some info on type features that you may find useful:

nil

The nil type is equivalent to undefined. A class attribute is marked as possibly nil if the read type is possibly nil. For properties where nil is possible on write, but not read, you can use undefined! or myNullableValue!, e.g. controlBehavior.parameters = undefined!.

Parameter Variants

Parameter tables with variants (having "additional attributes can be specified depending on type ...") are defined as a union of all variants. The type for a specific variant is prefixed with the variant name (e.g. AmmoDamageTechnologyModifier), or prefixed with "Other" for variants without extra properties (e.g. OtherTechnologyModifier).

Events

Event IDs (defines.events) hold type info for their corresponding event type and filters, which is used by various methods in script.

You can pass an event data type parameter to script.generate_event_name<T>(), and it will return a CustomEventId that includes type info.

Optional custominput name checking

You can optionally enable type-checking for custom input names (for script.on_event and CustomInputPrototype). To do so, specify names by extending the CustomInputNames interface like so:

declare module "factorio:common" {
  export interface CustomInputNames {
    "my-custom-input": any
  }
}

script.on_event("my-custom-input", () => {}) // type-checked

If not specified, CustomInputName defaults to just string.

Array-like classes

Classes that have an index operator, a length operator, and have an array-like structure subclass from (Readonly)Array. These are LuaInventory, LuaFluidBox, LuaTransportLine. This allows you to use these classes like arrays, e.g. having array methods and .length translating to the lua length operator. However, this means like typescript arrays, they are 0-indexed, not 1-indexed.

Read and write variants

For concepts that can take a table or array form, the main type (e.g. MapPosition) defines the table form, and an Array suffix (e.g. MapPositionArray) defines the array form. Concepts in a "read" position are in table form, and concepts in a "write" position may be either in table or array form (e.g. MapPosition | MapPositionArray). Concepts that include table-or-array concepts may have an additional Write variant (e.g. ScriptArea, ScriptAreaWrite).

Classes with subclasses

Some classes have attributes that only work for particular subclasses. For these classes (e.g. LuaEntity) there are specific types that you can optionally use:

  • A "Base" type (e.g. BaseEntity) which contains only members usable by all subclasses
  • Multiple subclass types, e.g. CraftingMachineEntity, which extends the base type with members specific to that subclass.

The original class name (e.g. LuaEntity) contains attributes for all subclasses.

For stricter types, use the Base type generally, and the specific subclass type when needed. You can also create your own type-narrowing functions:

function isCraftingMachineEntity(entity: BaseEntity): entity is CraftingMachineEntity {
  return entity.type === "crafting-machine"
}

LuaGuiElement

LuaGuiElement is broken up into a discriminated union, for each gui element type. Individual gui element types can be referred to by <Type>GuiElement, e.g. ButtonGuiElement.

Similarly, GuiSpec (the table passed to LuaGuiElement.add), is also a discriminated union. The type for a specific GuiSpec is <Type>GuiSpec, e.g. ListBoxGuiSpec. LuaGuiElement.add will return the appropriate gui element type corresponding to the GuiSpec type passed in.

This is done both to provide more accurate types, and for possible integration with JSX.

Support

If you find this project useful, consider tipping me on Kofi!