Skip to content
Kai Moschcau edited this page Jan 5, 2022 · 3 revisions

Hooks

The league types come with type definitions for the various hooks that Foundry VTT provides and also a way to register your own hook callback types. For foundry V9, the types also offer a way to register custom error hook callback types.

In general all hooks are typed here. This file should be the go-to source, if you want to find out about certain hooks.

Using the hooks

Some of the usage is already documented in the above linked file on the Hooks namespace. Type-wise there are two kinds of hooks in Foundry versions 8 or older and three kinds in 9 and newer:

  • static hooks (with static names)
  • dynamic hooks (with names composed at runtime)
  • error hook (V9+, with parameter types discriminatable on the first parameter)

Static hooks

Using these is easy, you only have to provide the name of the hook as first parameter to Hooks.on or Hooks.once and the types of the callback are automatically picked correctly:

Hooks.on("updateWorldTime", (worldTime, dt) => {
  worldTime; // number
  dt; // number
  // [...]
});

Dynamic hooks

This is a a bit less straight forward, as it requires you to provide a generic type parameter to Hooks.on or Hooks.once. For example like this:

Hooks.on<Hooks.CloseApplication<FormApplication>>("closeFormApplication", (app, jq) => {
  app // FormApplication
  jq // JQuery
  // [...]
});

Most of the time, the name of the hook has to include the name of the class that you want to call the hook for. So the hook name and the generic type parameter should fit together. Pay attention to the documentation either in the linked file or in the official Foundry API documentation. In most cases this is documented in the official API documentation as well.

error hook (V9+)

The error hook callback works mostly like a static hook. You can discriminate the error hook parameter types by the value of the first parameter. Though to achieve this, you have to specify the parameters of the hook as rest parameters (for example ...args). This is a limitation in typescript, where type discrimination can only be done on single variables and not on disjointed parameters.

Hooks.on("error", (...args) => {
  if (args[0] === "Canvas#draw")
    args[2].layer // CanvasLayer
  // [...]
})

Registering custom hook callback types

You can register you own custom hook callback types for static hooks by declaration merging into the interface Hooks.StaticCallbacks like so:

declare namespace Hooks {
  interface StaticCallbacks {
    fooBar: (baz: string, bar: number) => boolean;
  }
}

Your custom hook can then be accessed like this:

Hooks.on("fooBar", (baz, bar) => {
  baz; // string
  bar; // number
  return true;
});

Extending the dynamic callback types is currently not possible.

Registering custom error hook callback types (Foundry VTT V9+)

You can register you own custom error hook callback parameters by declaration merging into the interface Hooks.ErrorCallbackParameters like so:

declare namespace Hooks {
  interface ErrorCallbackParameters {
    "MyClass#myMethod": [location: "MyClass#myMethod", err: Error, data: { foo: number }];
  }
}

The key name doesn't matter, only the value of the location tuple entry does. You can then access it like this:

Hooks.on("error", (...args) => {
  if (args[0] === "MyClass#myMethod")
    args[2].foo; // number
});

You can also overwrite any of the Foundry specific error callback parameter types by declaration merging over the corresponding key in the interface.