From 35b5f04a7c9ca7ef414c5cd4f330277a44cd8145 Mon Sep 17 00:00:00 2001 From: dai Date: Fri, 6 Jun 2025 15:14:23 +0200 Subject: [PATCH] Hook typing improvements (#236) * Fix hook callback typings * Update docs * Add specialization * Simplify overloads * Remove generic --- docs/learn/overview.md | 24 ++++++++++++------------ jecs.d.ts | 22 +++++++++++++++++++--- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/docs/learn/overview.md b/docs/learn/overview.md index ff3db1b..37a991d 100644 --- a/docs/learn/overview.md +++ b/docs/learn/overview.md @@ -132,26 +132,26 @@ Component data generally need to adhere to a specific interface, and sometimes r ::: code-group ```luau [luau] local Transform = world:component() -world:set(Transform, OnAdd, function(entity) - -- A transform component has been added to an entity +world:set(Transform, OnAdd, function(entity, id, data) + -- A transform component `id` has been added with `data` to `entity` end) -world:set(Transform, OnRemove, function(entity) - -- A transform component has been removed from the entity +world:set(Transform, OnRemove, function(entity, id) + -- A transform component `id` has been removed from `entity` end) -world:set(Transform, OnChange, function(entity, value) - -- A transform component has been changed to value on the entity +world:set(Transform, OnChange, function(entity, id, data) + -- A transform component `id` has been changed to `data` on `entity` end) ``` ```typescript [typescript] const Transform = world.component(); -world.set(Transform, OnAdd, (entity) => { - // A transform component has been added to an entity +world.set(Transform, OnAdd, (entity, id, data) => { + // A transform component `id` has been added with `data` to `entity` }); -world.set(Transform, OnRemove, (entity) => { - // A transform component has been removed from the entity +world.set(Transform, OnRemove, (entity, id) => { + // A transform component `id` has been removed from `entity` }); -world.set(Transform, OnChange, (entity, value) => { - // A transform component has been changed to value on the entity +world.set(Transform, OnChange, (entity, id, data) => { + // A transform component `id` has been changed to `data` on `entity` }); ``` ::: diff --git a/jecs.d.ts b/jecs.d.ts index 72b3215..4ffb93b 100644 --- a/jecs.d.ts +++ b/jecs.d.ts @@ -151,6 +151,15 @@ export class World { */ add(entity: Entity, component: undefined extends InferComponent ? C : Id): void; + /** + * Installs a hook on the given component. + * @param component The target component. + * @param hook The hook to install. + * @param value The hook callback. + */ + set(component: Entity, hook: StatefulHook, value: (e: Entity, id: Id, data: T) => void): void; + set(component: Entity, hook: StatelessHook, value: (e: Entity, id: Id) => void): void; + /** * Assigns a value to a component on the given entity. * @param entity The target entity. @@ -280,9 +289,16 @@ export function pair_first(world: World, p: Pair): Entity

; */ export function pair_second(world: World, p: Pair): Entity; -export declare const OnAdd: Entity<(e: Entity) => void>; -export declare const OnRemove: Entity<(e: Entity) => void>; -export declare const OnChange: Entity<(e: Entity, value: unknown) => void>; +type StatefulHook = Entity<(e: Entity, id: Id, data: T) => void> & { + readonly __nominal_StatefulHook: unique symbol, +} +type StatelessHook = Entity<(e: Entity, id: Id) => void> & { + readonly __nominal_StatelessHook: unique symbol, +} + +export declare const OnAdd: StatefulHook; +export declare const OnRemove: StatelessHook; +export declare const OnChange: StatefulHook; export declare const ChildOf: Tag; export declare const Wildcard: Entity; export declare const w: Entity;