Repository: League-of-Foundry-Developers/foundry-vtt-types
Pull request #3186 (2025-02-19 23:32:28)

Types and tests for `FogManager`, `DetectionMode`(s), `VisionMode`(s), and `CanvasVisibility`
Pulled these out of the RenderFlags/PerceptionManager PR

also some associated touchup in a couple related files


Patch:
diff --git a/src/foundry/client-esm/canvas/sources/point-light-source.d.mts b/src/foundry/client-esm/canvas/sources/point-light-source.d.mts
index 4d56aca10..3334772cc 100644
--- a/src/foundry/client-esm/canvas/sources/point-light-source.d.mts
+++ b/src/foundry/client-esm/canvas/sources/point-light-source.d.mts
@@ -31,7 +31,7 @@ declare class PointLightSource<
    * @param config - The visibility test configuration
    * @returns Is the target object visible to this source?
    */
-  testVisibility(config?: CanvasVisibilityTestConfig): boolean;
+  testVisibility(config?: CanvasVisibility.TestConfig): boolean;
 
   /**
    * Can this LightSource theoretically detect a certain object based on its properties?
@@ -43,12 +43,13 @@ declare class PointLightSource<
 }
 
 declare namespace PointLightSource {
+  interface Any extends AnyPointLightSource {}
   type AnyConstructor = typeof AnyPointLightSource;
 
   type SourceData = PointEffectSourceMixin.SourceData & BaseLightSource.SourceData;
 }
 
-declare abstract class AnyPointLightSource extends PointLightSource {
+declare abstract class AnyPointLightSource extends PointLightSource<PointLightSource.SourceData, PointSourcePolygon> {
   constructor(arg0: never, ...args: never[]);
 }
 
diff --git a/src/foundry/client/config.d.mts b/src/foundry/client/config.d.mts
index f07822097..6df7dcab9 100644
--- a/src/foundry/client/config.d.mts
+++ b/src/foundry/client/config.d.mts
@@ -989,8 +989,11 @@ declare global {
         bright: number;
       };
 
-      /** @defaultValue `FogManager` */
-      fogManager: FogManager.AnyConstructor;
+      /**
+       * @defaultValue `FogManager`
+       * @remarks Can't be `AnyConstructor` because Foundry assumes it can call `new` with the same arguments FogManager accepts
+       */
+      fogManager: typeof FogManager;
 
       polygonBackends: {
         /** @defaultValue `typeof ClockwiseSweepPolygon` */
diff --git a/src/foundry/client/pixi/core/shapes/source-polygon.d.mts b/src/foundry/client/pixi/core/shapes/source-polygon.d.mts
index ce9181171..d5a6916db 100644
--- a/src/foundry/client/pixi/core/shapes/source-polygon.d.mts
+++ b/src/foundry/client/pixi/core/shapes/source-polygon.d.mts
@@ -91,7 +91,10 @@ declare global {
      * @param intersectionOptions - Options passed to the shape intersection method
      * @returns A new constrained polygon
      */
-    applyConstraint(constraint: PIXI.Polygon, intersectionOptions?: PIXI.Polygon.IntersectPolygonOptions): this;
+    applyConstraint(
+      constraint: PIXI.Polygon,
+      intersectionOptions?: PIXI.Polygon.IntersectPolygonOptions, // not:null (property set on it via `??=`)
+    ): this;
     applyConstraint(constraint: PIXI.Circle, intersectionOptions?: PIXI.Circle.WACIntersectPolygonOptions): this;
     applyConstraint(constraint: PIXI.Circle, intersectionOptions?: PIXI.Circle.ClipperLibIntersectPolygonOptions): this;
     applyConstraint(constraint: PIXI.Rectangle, intersectionOptions?: PIXI.Rectangle.WACIntersectPolygonOptions): this;
@@ -116,9 +119,11 @@ declare global {
      * @param mode        - The collision mode to test: "any", "all", or "closest"
      *                      (default: "all")
      * @returns The collision result depends on the mode of the test:
-     *          * any: returns a boolean for whether any collision occurred
-     *          * all: returns a sorted array of PolygonVertex instances
-     *          * closest: returns a PolygonVertex instance or null
+     *          - any: returns a boolean for whether any collision occurred
+     *          - all: returns a sorted array of PolygonVertex instances
+     *          - closest: returns a PolygonVertex instance or null
+     * @remarks Despite being an `={}` parameter, `options` is required as it must be a valid
+     * `PointSourcePolygon.Config`, which has a required property (`type`)
      */
     static testCollision<Mode extends PointSourcePolygon.CollisionModes | undefined = undefined>(
       origin: Canvas.Point,
diff --git a/src/foundry/client/pixi/layers/effects/visibility.d.mts b/src/foundry/client/pixi/layers/effects/visibility.d.mts
index 3325db31c..bae494263 100644
--- a/src/foundry/client/pixi/layers/effects/visibility.d.mts
+++ b/src/foundry/client/pixi/layers/effects/visibility.d.mts
@@ -1,4 +1,4 @@
-import type { EmptyObject, HandleEmptyObject, InexactPartial, ValueOf } from "fvtt-types/utils";
+import type { HandleEmptyObject, InexactPartial, IntentionalPartial } from "fvtt-types/utils";
 
 declare global {
   /**
@@ -9,11 +9,13 @@ declare global {
   class CanvasVisibility extends CanvasLayer {
     /**
      * The currently revealed vision.
+     * @remarks Only `undefined` prior to first draw
      */
     vision: CanvasVisionMask.CanvasVisionContainer | undefined;
 
     /**
      * The exploration container which tracks exploration progress.
+     * @remarks Only `undefined` prior to first draw
      */
     explored: PIXI.Container | undefined;
 
@@ -22,6 +24,9 @@ declare global {
      */
     visibilityOverlay: PIXI.Sprite | undefined;
 
+    /** @remarks Doesn't exist until it's set on draw */
+    filter?: VisibilityFilter.ConfiguredInstance;
+
     /**
      * The active vision source data object
      * @defaultValue
@@ -32,10 +37,7 @@ declare global {
      * }
      * ```
      */
-    visionModeData: {
-      source: foundry.canvas.sources.PointVisionSource.Any | null | undefined;
-      activeLightingOptions: VisionMode["_source"]["lighting"] | EmptyObject;
-    };
+    visionModeData: CanvasVisibility.VisionModeData;
 
     /**
      * Define whether each lighting layer is enabled, required, or disabled by this vision mode.
@@ -50,13 +52,7 @@ declare global {
      * }
      * ```
      */
-    lightingVisibility: {
-      illumination: CanvasVisibility.LightingVisibility;
-      background: CanvasVisibility.LightingVisibility;
-      coloration: CanvasVisibility.LightingVisibility;
-      darkness: CanvasVisibility.LightingVisibility;
-      any: boolean;
-    };
+    lightingVisibility: CanvasVisibility.LightingVisibility;
 
     /**
      * A status flag for whether the layer initialization workflow has succeeded.
@@ -65,8 +61,9 @@ declare global {
 
     /**
      * Indicates whether containment filtering is required when rendering vision into a texture
+     * @remarks Foundry marked `@internal`
      */
-    protected get needsContainment(): boolean;
+    get needsContainment(): boolean;
 
     /**
      * Does the currently viewed Scene support Token field of vision?
@@ -76,17 +73,21 @@ declare global {
 
     /**
      * The configured options used for the saved fog-of-war texture.
+     * @remarks Only `undefined` before first `#draw()`
      */
-    get textureConfiguration(): VisibilityTextureConfiguration | undefined;
+    get textureConfiguration(): CanvasVisibility.TextureConfiguration | undefined;
 
     /**
      * Optional overrides for exploration sprite dimensions.
      *
-     * @privateRemarks Foundry types this parameter as `FogTextureConfiguration`, and
-     * unlike the other place they used this type seeming in error, only `rect`'s
-     * `x, y, width, height` properties are accessed, so I'm assuming they meant Rectangle
+     * @privateRemarks Foundry types this parameter as `FogTextureConfiguration` in v12.331 which is plainly wrong even if it didn't not exist
+     * v13.335 types as `PIXI.Rectable | undefined`, but only x/y/width/height are ever accessed, and only then if this has been set to something
+     * other than `undefined`, and in fact nothing in core ever does.
      */
-    set explorationRect(rect: Canvas.Rectangle);
+    set explorationRect(rect: Canvas.Rectangle | undefined);
+
+    /** @remarks This getter doesn't actually exist, it's only here to correct the type inferred from the setter */
+    get explorationRect(): undefined;
 
     /**
      * Initialize all Token vision sources which are present on this layer
@@ -132,48 +133,19 @@ declare global {
      */
     testVisibility(
       point: Canvas.Point,
-      /**
-       * @remarks Can't be NullishProps because `tolerance` gets passed directly to `_createVisibilityTestConfig`,
-       * where a default is provided only for `undefined` with `{ tolerance=2 }`, which must be numeric
-       * */
-      options?: InexactPartial<{
-        /**
-         * A numeric radial offset which allows for a non-exact match.
-         * For example, if tolerance is 2 then the test will pass if the point
-         * is within 2px of a vision polygon.
-         */
-        tolerance: number;
-
-        /**
-         * An optional reference to the object whose visibility is being tested
-         */
-        object: PlaceableObject | null;
-      }>,
+      options?: CanvasVisibility.TestVisibilityOptions, // not:null (destructured when passed to _createVisibilityTestConfig)
     ): boolean;
 
     /**
      * Create the visibility test config.
      * @param point   - The point in space to test, an object with coordinates x and y.
      * @param options - Additional options which modify visibility testing.
+     * @remarks Foundry marked `@internal`
      */
-    _createVisibilityTestConfig(
+    protected _createVisibilityTestConfig(
       point: Canvas.Point,
-      /** @remarks Can't be NullishProps because a default for `tolerance` is provided only for `undefined` with `{ tolerance=2 }`, which must be numeric */
-      options?: InexactPartial<{
-        /**
-         * A numeric radial offset which allows for a non-exact match.
-         * For example, if tolerance is 2 then the test will pass if the point
-         * is within 2px of a vision polygon
-         * @defaultValue `2`
-         */
-        tolerance: number;
-
-        /**
-         * An optional reference to the object whose visibility is being tested
-         */
-        object: PlaceableObject | null;
-      }>,
-    ): CanvasVisibilityTestConfig;
+      options?: CanvasVisibility.CreateTestConfigOptions, // not:null (destructured)
+    ): CanvasVisibility.TestConfig;
 
     /**
      * @deprecated since v11, will be removed in v13
@@ -186,40 +158,86 @@ declare global {
     interface Any extends AnyCanvasVisibility {}
     type AnyConstructor = typeof AnyCanvasVisibility;
 
-    type LightingVisibility = ValueOf<typeof VisionMode.LIGHTING_VISIBILITY>;
-
     interface DrawOptions extends CanvasLayer.DrawOptions {}
 
     interface TearDownOptions extends CanvasLayer.TearDownOptions {}
-  }
 
-  /**
-   * @privateRemarks This is name foundry has for the return tyoe of `CanvasVisibility#configureVisibilityTexture`
-   * The FogTextureConfiguration references seem to be in error
-   */
-  interface VisibilityTextureConfiguration {
-    resolution: number;
-    width: number;
-    height: number;
-    mipmap: PIXI.MIPMAP_MODES;
-    multisample: PIXI.MSAA_QUALITY;
-    scaleMode: PIXI.SCALE_MODES;
-    alphaMode: PIXI.ALPHA_MODES;
-    format: PIXI.FORMATS;
-  }
+    type TestObject = PlaceableObject.Any | null;
 
-  interface CanvasVisibilityTest {
-    point: PIXI.Point;
-    elevation: number;
-    los: Map<foundry.canvas.sources.PointVisionSource.Any, boolean>;
-  }
+    interface VisionModeData {
+      source: foundry.canvas.sources.PointVisionSource.Any | null | undefined;
+      activeLightingOptions: IntentionalPartial<VisionMode["lighting"]>;
+    }
+
+    interface LightingVisibility {
+      illumination: VisionMode.LIGHTING_VISIBILITY;
+      background: VisionMode.LIGHTING_VISIBILITY;
+      coloration: VisionMode.LIGHTING_VISIBILITY;
+      darkness: VisionMode.LIGHTING_VISIBILITY;
+      /** @remarks Only set `false` if all other keys are `VisionMode.LIGHTING_VISIBILITY.DISABLED` */
+      any: boolean;
+    }
 
-  interface CanvasVisibilityTestConfig {
-    /** The target object */
-    object: PlaceableObject | null;
+    interface TestVisibilityOptions extends CreateTestConfigOptions {}
+
+    /** @internal */
+    type _CreateTestConfigOptions = InexactPartial<{
+      /**
+       * A numeric radial offset which allows for a non-exact match.
+       * For example, if tolerance is 2 then the test will pass if the point
+       * is within 2px of a vision polygon
+       * @defaultValue `2`
+       * @remarks Can't be `null` because it only has a parameter default
+       */
+      tolerance: number;
 
-    /** An array of visibility tests */
-    tests: CanvasVisibilityTest[];
+      /**
+       * An optional reference to the object whose visibility is being tested
+       * @defaultValue `null`
+       */
+      object: TestObject;
+    }>;
+
+    interface CreateTestConfigOptions extends _CreateTestConfigOptions {}
+
+    /** @internal */
+    interface _TestConfigOptional {
+      /**
+       * The target object
+       * @defaultValue `null`
+       * @remarks Only checked in `#_canDetect` for `instanceof Token`
+       */
+      object: TestObject;
+    }
+
+    /** @internal */
+    interface _TestConfigRequired {
+      /** An array of visibility tests */
+      tests: CanvasVisibility.Test[];
+    }
+
+    interface TestConfig extends _TestConfigRequired, _TestConfigOptional {}
+
+    interface Test {
+      point: Canvas.Point;
+      elevation: number;
+      los: Map<foundry.canvas.sources.PointVisionSource.Any, boolean>;
+    }
+
+    /**
+     * @privateRemarks This is a fixed subset of `PIXI.IBaseTextureOptions` that `CanvasVisibility##createTextureConfiguration` produces.
+     * Since it's generated by a private method and stored in a private property, it's not meaninfully extensible (`canvas.visibility.textureConfiguration.foo = "bar"` doesn't count)
+     */
+    interface TextureConfiguration {
+      resolution: number;
+      width: number;
+      height: number;
+      mipmap: PIXI.MIPMAP_MODES;
+      multisample: PIXI.MSAA_QUALITY;
+      scaleMode: PIXI.SCALE_MODES;
+      alphaMode: PIXI.ALPHA_MODES;
+      format: PIXI.FORMATS;
+    }
   }
 }
 
diff --git a/src/foundry/client/pixi/perception/clockwise-sweep.d.mts b/src/foundry/client/pixi/perception/clockwise-sweep.d.mts
index 6d3b6a75e..55a421a95 100644
--- a/src/foundry/client/pixi/perception/clockwise-sweep.d.mts
+++ b/src/foundry/client/pixi/perception/clockwise-sweep.d.mts
@@ -40,7 +40,7 @@ declare global {
     // @ts-expect-error Getter/setter routine is deprecated functionality as of v11, removed in v13
     rays: PolygonRay[];
 
-    override initialize(origin: Canvas.Point, config?: PointSourcePolygon.Config): void;
+    override initialize(origin: Canvas.Point, config: PointSourcePolygon.Config): void;
 
     clone(): this;
 
@@ -174,7 +174,7 @@ declare global {
       boundingBox: PIXI.Rectangle;
     }
     /**
-     * @privateRemarks Foundry types this as `Record<Edge.EdgeTypes, 0 | 1 | 2>`, but some keys are mutually exclusive,
+     * @remarks Foundry types this as `Record<Edge.EdgeTypes, 0 | 1 | 2>`, but some keys are mutually exclusive,
      * and none are ever set to `0`, they're simply omitted and then tested for truthiness in `#_testEdgeInclusion`
      */
     type DetermineEdgesReturn = IntentionalPartial<Record<Edge.EdgeTypes, 1 | 2>>;
diff --git a/src/foundry/client/pixi/perception/detection-mode.d.mts b/src/foundry/client/pixi/perception/detection-mode.d.mts
index cf374bb3e..ba3f691aa 100644
--- a/src/foundry/client/pixi/perception/detection-mode.d.mts
+++ b/src/foundry/client/pixi/perception/detection-mode.d.mts
@@ -1,24 +1,9 @@
-import type { InexactPartial, ValueOf } from "fvtt-types/utils";
+import type { Brand, NullishProps } from "fvtt-types/utils";
 import type { fields } from "../../../common/data/module.d.mts";
 import type { TokenDetectionMode } from "../../../common/documents/_types.d.mts";
-
-type DataSchema = foundry.data.fields.DataSchema;
+import type { DataSchema } from "../../../common/data/fields.d.mts";
 
 declare global {
-  namespace DetectionMode {
-    interface Schema extends DataSchema {
-      id: fields.StringField<{ blank: false }>;
-      label: fields.StringField<{ blank: false }>;
-      tokenConfig: fields.BooleanField<{ initial: true }>;
-      walls: fields.BooleanField<{ initial: true }>;
-      angle: fields.BooleanField<{ initial: true }>;
-      type: fields.NumberField<{
-        initial: typeof DetectionMode.DETECTION_TYPES.SIGHT;
-        choices: ValueOf<typeof DetectionMode.DETECTION_TYPES>[];
-      }>;
-    }
-  }
-
   /**
    * A Detection Mode which can be associated with any kind of sense/vision/perception.
    * A token could have multiple detection modes.
@@ -39,22 +24,14 @@ declare global {
     /**
      * The type of the detection mode.
      * @see CONST.WALL_RESTRICTION_TYPES
+     * @remarks Set via `Object.defineProperty` with a frozen object, so `readonly` is justified both here and for the interface properties
      */
-    static DETECTION_TYPES: {
-      /** Sight, and anything depending on light perception */
-      SIGHT: 0;
-      /** What you can hear. Includes echolocation for bats per example */
-      SOUND: 1;
-      /** This is mostly a sense for touch and vibration, like tremorsense, movement detection, etc. */
-      MOVE: 2;
-      /** Can't fit in other types (smell, life sense, trans-dimensional sense, sense of humor...) */
-      OTHER: 3;
-    };
+    static readonly DETECTION_TYPES: DetectionMode.DetectionTypes;
 
     /**
      * The identifier of the basic sight detection mode.
      */
-    static BASIC_MODE_ID: "basicSight";
+    static readonly BASIC_MODE_ID: "basicSight";
 
     /**
      * Test visibility of a target object or array of points for a specific vision source.
@@ -66,7 +43,7 @@ declare global {
     testVisibility(
       visionSource: foundry.canvas.sources.PointVisionSource.Any,
       mode: TokenDetectionMode,
-      { object, tests }: InexactPartial<CanvasVisibilityTestConfig>,
+      config?: DetectionMode.TestConfig, // not:null (destructured)
     ): boolean;
 
     /**
@@ -76,7 +53,10 @@ declare global {
      * @param target       - The target object being tested
      * @returns Can the target object theoretically be detected by this vision source?
      */
-    protected _canDetect(visionSource: foundry.canvas.sources.PointVisionSource.Any, target: PlaceableObject): boolean;
+    protected _canDetect(
+      visionSource: foundry.canvas.sources.PointVisionSource.Any,
+      target: CanvasVisibility.TestObject,
+    ): boolean;
 
     /**
      * Evaluate a single test point to confirm whether it is visible.
@@ -89,8 +69,8 @@ declare global {
     protected _testPoint(
       visionSource: foundry.canvas.sources.PointVisionSource.Any,
       mode: TokenDetectionMode,
-      target: PlaceableObject,
-      test: CanvasVisibilityTest,
+      target: CanvasVisibility.TestObject,
+      test: CanvasVisibility.Test,
     ): boolean;
 
     /**
@@ -106,8 +86,8 @@ declare global {
     protected _testLOS(
       visionSource: foundry.canvas.sources.PointVisionSource.Any,
       mode: TokenDetectionMode,
-      target: PlaceableObject,
-      test: CanvasVisibilityTest,
+      target: CanvasVisibility.TestObject,
+      test: CanvasVisibility.Test,
     ): boolean;
 
     /**
@@ -121,8 +101,8 @@ declare global {
     protected _testAngle(
       visionSource: foundry.canvas.sources.PointVisionSource.Any,
       mode: TokenDetectionMode,
-      target: PlaceableObject,
-      test: CanvasVisibilityTest,
+      target: CanvasVisibility.TestObject,
+      test: CanvasVisibility.Test,
     ): boolean;
 
     /**
@@ -136,11 +116,54 @@ declare global {
     protected _testRange(
       visionSource: foundry.canvas.sources.PointVisionSource.Any,
       mode: TokenDetectionMode,
-      target: PlaceableObject,
-      test: CanvasVisibilityTest,
+      target: CanvasVisibility.TestObject,
+      test: CanvasVisibility.Test,
     ): boolean;
   }
 
+  namespace DetectionMode {
+    interface Any extends AnyDetectionMode {}
+    type AnyConstructor = typeof AnyDetectionMode;
+
+    interface Schema extends DataSchema {
+      id: fields.StringField<{ blank: false }>;
+
+      label: fields.StringField<{ blank: false }>;
+
+      /** If this DM is available in Token Config UI */
+      tokenConfig: fields.BooleanField<{ initial: true }>;
+
+      /** If this DM is constrained by walls */
+      walls: fields.BooleanField<{ initial: true }>;
+
+      /** If this DM is constrained by the vision angle */
+      angle: fields.BooleanField<{ initial: true }>;
+
+      type: fields.NumberField<{
+        initial: DetectionMode.DETECTION_TYPES;
+        choices: DetectionMode.DETECTION_TYPES[];
+      }>;
+    }
+
+    /** @see CanvasVisibility.TestConfig */
+    interface TestConfig
+      extends CanvasVisibility._TestConfigRequired,
+        NullishProps<CanvasVisibility._TestConfigOptional> {}
+
+    type DETECTION_TYPES = Brand<number, "DetectionMode.DETECTION_TYPES">;
+
+    interface DetectionTypes {
+      /** Sight, and anything depending on light perception */
+      readonly SIGHT: 0 & DETECTION_TYPES;
+      /** What you can hear. Includes echolocation for bats per example */
+      readonly SOUND: 1 & DETECTION_TYPES;
+      /** This is mostly a sense for touch and vibration, like tremorsense, movement detection, etc. */
+      readonly MOVE: 2 & DETECTION_TYPES;
+      /** Can't fit in other types (smell, life sense, trans-dimensional sense, sense of humor...) */
+      readonly OTHER: 3 & DETECTION_TYPES;
+    }
+  }
+
   /**
    * This detection mode tests whether the target is visible due to being illuminated by a light source.
    * By default tokens have light perception with an infinite range if light perception isn't explicitely
@@ -149,17 +172,22 @@ declare global {
   class DetectionModeLightPerception extends DetectionMode {
     protected override _canDetect(
       visionSource: foundry.canvas.sources.PointVisionSource.Any,
-      target: PlaceableObject,
+      target: CanvasVisibility.TestObject,
     ): boolean;
 
     protected override _testPoint(
       visionSource: foundry.canvas.sources.PointVisionSource.Any,
       mode: TokenDetectionMode,
-      target: PlaceableObject,
-      test: CanvasVisibilityTest,
+      target: CanvasVisibility.TestObject,
+      test: CanvasVisibility.Test,
     ): boolean;
   }
 
+  namespace DetectionModeLightPerception {
+    interface Any extends AnyDetectionModeLightPerception {}
+    type AnyConstructor = typeof AnyDetectionModeLightPerception;
+  }
+
   /**
    * A special detection mode which models a form of darkvision (night vision).
    * This mode is the default case which is tested first when evaluating visibility of objects.
@@ -168,10 +196,15 @@ declare global {
   class DetectionModeBasicSight extends DetectionMode {
     protected override _canDetect(
       visionSource: foundry.canvas.sources.PointVisionSource.Any,
-      target: PlaceableObject,
+      target: CanvasVisibility.TestObject,
     ): boolean;
   }
 
+  namespace DetectionModeBasicSight {
+    interface Any extends AnyDetectionModeBasicSight {}
+    type AnyConstructor = typeof AnyDetectionModeBasicSight;
+  }
+
   /**
    * Detection mode that see invisible creatures.
    * This detection mode allows the source to:
@@ -179,36 +212,75 @@ declare global {
    * - The "See" version needs sight and is affected by blindness
    */
   class DetectionModeInvisibility extends DetectionMode {
-    static override getDetectionFilter(): PIXI.Filter | undefined;
+    static override getDetectionFilter(): PIXI.Filter;
 
     protected override _canDetect(
       visionSource: foundry.canvas.sources.PointVisionSource.Any,
-      target: PlaceableObject,
+      target: CanvasVisibility.TestObject,
     ): boolean;
   }
 
+  namespace DetectionModeInvisibility {
+    interface Any extends AnyDetectionModeInvisibility {}
+    type AnyConstructor = typeof AnyDetectionModeInvisibility;
+  }
+
   /**
    * Detection mode that see creatures in contact with the ground.
    */
   class DetectionModeTremor extends DetectionMode {
-    static override getDetectionFilter(): PIXI.Filter | undefined;
+    static override getDetectionFilter(): PIXI.Filter;
 
     protected override _canDetect(
       visionSource: foundry.canvas.sources.PointVisionSource.Any,
-      target: PlaceableObject,
+      target: CanvasVisibility.TestObject,
     ): boolean;
   }
 
+  namespace DetectionModeTremor {
+    interface Any extends AnyDetectionModeTremor {}
+    type AnyConstructor = typeof AnyDetectionModeTremor;
+  }
+
   /**
    * Detection mode that see ALL creatures (no blockers).
    * If not constrained by walls, see everything within the range.
    */
   class DetectionModeAll extends DetectionMode {
-    static override getDetectionFilter(): PIXI.Filter | undefined;
+    static override getDetectionFilter(): PIXI.Filter;
 
     protected override _canDetect(
       visionSource: foundry.canvas.sources.PointVisionSource.Any,
-      target: PlaceableObject,
+      target: CanvasVisibility.TestObject,
     ): boolean;
   }
+
+  namespace DetectionModeAll {
+    interface Any extends AnyDetectionModeAll {}
+    type AnyConstructor = typeof AnyDetectionModeAll;
+  }
+}
+
+declare abstract class AnyDetectionMode extends DetectionMode {
+  constructor(arg0: never, ...args: never[]);
+}
+
+declare abstract class AnyDetectionModeLightPerception extends DetectionModeLightPerception {
+  constructor(arg0: never, ...args: never[]);
+}
+
+declare abstract class AnyDetectionModeBasicSight extends DetectionModeBasicSight {
+  constructor(arg0: never, ...args: never[]);
+}
+
+declare abstract class AnyDetectionModeInvisibility extends DetectionModeInvisibility {
+  constructor(arg0: never, ...args: never[]);
+}
+
+declare abstract class AnyDetectionModeTremor extends DetectionModeTremor {
+  constructor(arg0: never, ...args: never[]);
+}
+
+declare abstract class AnyDetectionModeAll extends DetectionModeAll {
+  constructor(arg0: never, ...args: never[]);
 }
diff --git a/src/foundry/client/pixi/perception/fog.d.mts b/src/foundry/client/pixi/perception/fog.d.mts
index ec6c82925..dbe38b6c8 100644
--- a/src/foundry/client/pixi/perception/fog.d.mts
+++ b/src/foundry/client/pixi/perception/fog.d.mts
@@ -1,4 +1,4 @@
-import type { DisplayObject } from "pixi.js";
+import type { FixedInstanceType } from "../../../../utils/index.d.mts";
 
 declare global {
   /**
@@ -9,23 +9,26 @@ declare global {
      * The FogExploration document which applies to this canvas view
      * @defaultValue `null`
      */
-    exploration: FogExploration | null;
+    exploration: FogExploration.ConfiguredInstance | null;
 
     /**
      * Track whether we have pending fog updates which have not yet been saved to the database
      * @defaultValue `false`
+     * @remarks Foundry marked `@internal`
      */
-    _updated: boolean;
+    protected _updated: boolean;
 
     /**
      * Texture extractor
+     * @remarks Only `undefined` before first `#initialize()`ation. Set to `null` if `TextureExtractor` creation fails, and will not retry from that state.
      */
-    get extractor(): TextureExtractor;
+    get extractor(): TextureExtractor | undefined | null;
 
     /**
      * Define the number of fog refresh needed before the fog texture is extracted and pushed to the server.
+     * @defaultValue `70`
      */
-    static COMMIT_THRESHOLD: 70;
+    static COMMIT_THRESHOLD: number;
 
     /**
      * The exploration SpriteMesh which holds the fog exploration texture.
@@ -34,23 +37,27 @@ declare global {
 
     /**
      * The configured options used for the saved fog-of-war texture.
+     * @remarks Only `undefined` prior to the first time the canvas visibility layer is `#draw()`n
      */
-    get textureConfiguration(): VisibilityTextureConfiguration;
+    get textureConfiguration(): CanvasVisibility["textureConfiguration"];
 
     /**
      * Does the currently viewed Scene support Token field of vision?
      */
+    //TODO: make `Scene.Implementation["tokenVision"]` when docsv2 is done
     get tokenVision(): boolean;
 
     /**
      * Does the currently viewed Scene support fog of war exploration?
      */
+    //TODO: make `Scene.Implementation["fog"]["exploration"]` when docsv2 is done
     get fogExploration(): boolean;
 
     /**
      * Create the exploration display object with or without a provided texture.
+     * @privateRemarks Despite Foundry only typing this as returning `DisplayObject` in 12.331, it always returns a `SpriteMesh`
      */
-    protected _createExplorationObject(tex?: PIXI.Texture | PIXI.RenderTexture): DisplayObject;
+    protected _createExplorationObject(tex?: PIXI.Texture | PIXI.RenderTexture | null): SpriteMesh;
 
     /**
      * Initialize fog of war - resetting it when switching scenes or re-drawing the canvas
@@ -95,42 +102,49 @@ declare global {
      * @param base64Image - The extracted base64 image data
      * @returns Exploration data to update
      */
-    protected _prepareFogUpdateData(base64Image: string): foundry.documents.BaseFogExploration.UpdateData;
+    protected _prepareFogUpdateData(base64Image: string): FogExploration.UpdateData;
 
     /**
      * If fog of war data is reset from the server, deactivate the current fog and initialize the exploration.
-     * @internal
+     * @remarks Foundry marked `@internal`, called externally in the `fogReset` socket handler
      */
-    _handleReset(): Promise<void>;
+    protected _handleReset(): Promise<void>;
 
     /**
      * @deprecated since v11, will be removed in v13
-     * @remarks pending is deprecated and redirected to the exploration container
+     * @remarks "pending is deprecated and redirected to the exploration container"
      */
     get pending(): CanvasVisibility["explored"];
 
     /**
      * @deprecated since v11, will be removed in v13
-     * @remarks revealed is deprecated and redirected to the exploration container
+     * @remarks "revealed is deprecated and redirected to the exploration container"
      */
     get revealed(): CanvasVisibility["explored"];
 
     /**
      * @deprecated since v11, will be removed in v13
-     * @remarks update is obsolete and always returns true. The fog exploration does not record position anymore.
+     * @remarks "update is obsolete and always returns true. The fog exploration does not record position anymore."
+     *
+     * Both parameters are unused
      */
-    update(source: any, force: boolean): true;
+    update(source: any, force?: boolean | null): true;
 
     /**
      * @deprecated since v11, will be removed in v13
-     * @remarks resolution is deprecated and redirected to CanvasVisibility#textureConfiguration
+     * @remarks "resolution is deprecated and redirected to CanvasVisibility#textureConfiguration"
+     *
+     * Probable Bug Note: Returns the entire `textureConfiguration` object, not just its `resolution` property
      */
     get resolution(): CanvasVisibility["textureConfiguration"];
   }
 
   namespace FogManager {
-    type Any = AnyFogManager;
+    interface Any extends AnyFogManager {}
     type AnyConstructor = typeof AnyFogManager;
+
+    type ConfiguredClass = CONFIG["Canvas"]["fogManager"];
+    type ConfiguredInstance = FixedInstanceType<ConfiguredClass>;
   }
 }
 
diff --git a/src/foundry/client/pixi/perception/vision-mode.d.mts b/src/foundry/client/pixi/perception/vision-mode.d.mts
index 0b8f92ec4..fd0b2b23c 100644
--- a/src/foundry/client/pixi/perception/vision-mode.d.mts
+++ b/src/foundry/client/pixi/perception/vision-mode.d.mts
@@ -1,6 +1,8 @@
-import type { AnyObject, InexactPartial, SimpleMerge, ValueOf } from "fvtt-types/utils";
+import type { Brand, InterfaceToObject, SimpleMerge } from "fvtt-types/utils";
 import type { fields } from "../../../common/data/module.d.mts";
 import DataField = foundry.data.fields.DataField;
+import type DataModel from "../../../common/abstract/data.d.mts";
+import type PointVisionSource from "../../../client-esm/canvas/sources/point-vision-source.d.mts";
 
 type DataSchema = foundry.data.fields.DataSchema;
 
@@ -24,25 +26,60 @@ declare global {
 
     // TODO: _cast blatantly breaks inheritance so this is difficult to work with
     /** @remarks The value provided to a ShaderField must be an AbstractBaseShader subclass. */
-    override _cast(value: any): Exclude<InitializedType, undefined | null>; // typeof AbstractBaseShader;
+    override _cast(value: any): NonNullable<InitializedType>; // typeof AbstractBaseShader;
+  }
+
+  namespace ShaderField {
+    type Options = DataField.Options<typeof AbstractBaseShader>;
+
+    type DefaultOptions = SimpleMerge<
+      DataField.DefaultOptions,
+      {
+        nullable: true;
+        initial: undefined;
+      }
+    >;
+
+    /**
+     * A helper type for the given options type merged into the default options of the BooleanField class.
+     * @typeParam Opts - the options that override the default options
+     */
+    type MergedOptions<Opts extends Options> = SimpleMerge<DefaultOptions, Opts>;
+
+    /**
+     * A shorthand for the assignment type of a BooleanField class.
+     * @typeParam Opts - the options that override the default options
+     */
+    type AssignmentType<Opts extends Options> = DataField.DerivedAssignmentType<
+      typeof AbstractBaseShader,
+      MergedOptions<Opts>
+    >;
+
+    /**
+     * A shorthand for the initialized type of a BooleanField class.
+     * @typeParam Opts - the options that override the default options
+     */
+    type InitializedType<Opts extends Options> = DataField.DerivedInitializedType<
+      typeof AbstractBaseShader,
+      MergedOptions<Opts>
+    >;
   }
 
   /**
    * A Vision Mode which can be selected for use by a Token.
    * The selected Vision Mode alters the appearance of various aspects of the canvas while that Token is the POV.
    */
-  class VisionMode extends foundry.abstract.DataModel<VisionMode.Schema> {
-    /**
-     * Construct a Vision Mode using provided configuration parameters and callback functions.
-     * @param data    - Data which fulfills the model defined by the VisionMode schema.
-     * @param options - Additional options passed to the DataModel constructor.
-     */
-    constructor(data: InexactPartial<any>, options?: AnyObject);
+  class VisionMode extends foundry.abstract.DataModel<
+    VisionMode.Schema,
+    DataModel.Any | null,
+    InterfaceToObject<VisionMode.ExtraConstructorOptions>
+  > {
+    // A constructor override has been omitted as there are no typing changes
 
     static defineSchema(): VisionMode.Schema;
 
     /** The lighting illumination levels which are supported. */
-    static LIGHTING_LEVELS: typeof CONST.LIGHTING_LEVELS;
+    static LIGHTING_LEVELS: typeof foundry.CONST.LIGHTING_LEVELS;
 
     /**
      * Flags for how each lighting channel should be rendered for the currently active vision modes:
@@ -50,11 +87,7 @@ declare global {
      * - Enabled: this lighting layer is rendered normally, and the shaders can choose if they should be rendered or not.
      * - Required: the lighting layer is rendered, the shaders does not decide.
      */
-    static LIGHTING_VISIBILITY: {
-      DISABLED: 0;
-      ENABLED: 1;
-      REQUIRED: 2;
-    };
+    static LIGHTING_VISIBILITY: VisionMode.LightingVisibility;
 
     /**
      * A flag for whether this vision source is animated
@@ -72,83 +105,66 @@ declare global {
      * Special activation handling that could be implemented by VisionMode subclasses
      * @param source - Activate this VisionMode for a specific source
      */
-    _activate(source: foundry.canvas.sources.PointVisionSource.Any): void;
+    _activate(source: PointVisionSource.Any): void;
 
     /**
      * Special deactivation handling that could be implemented by VisionMode subclasses
      * @param source - Deactivate this VisionMode for a specific source
      */
-    _deactivate(source: foundry.canvas.sources.PointVisionSource.Any): void;
+    _deactivate(source: PointVisionSource.Any): void;
 
     /**
      * Special handling which is needed when this Vision Mode is activated for a VisionSource.
      * @param source - Activate this VisionMode for a specific source
      */
-    activate(source: foundry.canvas.sources.PointVisionSource.Any): void;
+    activate(source: PointVisionSource.Any): void;
 
     /**
      * Special handling which is needed when this Vision Mode is deactivated for a VisionSource.
      * @param source - Deactivate this VisionMode for a specific source
      */
-    deactivate(source: foundry.canvas.sources.PointVisionSource.Any): void;
+    deactivate(source: PointVisionSource.Any): void;
 
     /**
      * An animation function which runs every frame while this Vision Mode is active.
      * @param dt - The deltaTime passed by the PIXI Ticker
+     * @remarks Calls `RenderedEffectSource#animateTime` with `this` set to this `VisionMode`
      */
     animate(dt: number): void;
   }
 
-  namespace ShaderField {
-    type Options = DataField.Options<typeof AbstractBaseShader>;
-
-    type DefaultOptions = SimpleMerge<
-      DataField.DefaultOptions,
-      {
-        nullable: true;
-        initial: undefined;
-      }
-    >;
-
-    /**
-     * A helper type for the given options type merged into the default options of the BooleanField class.
-     * @typeParam Opts - the options that override the default options
-     */
-    type MergedOptions<Opts extends Options> = SimpleMerge<DefaultOptions, Opts>;
+  namespace VisionMode {
+    type LIGHTING_VISIBILITY = Brand<number, "VisionMode.LIGHTING_VISIBILITY">;
 
-    /**
-     * A shorthand for the assignment type of a BooleanField class.
-     * @typeParam Opts - the options that override the default options
-     */
-    type AssignmentType<Opts extends Options> = foundry.data.fields.DataField.DerivedAssignmentType<
-      typeof AbstractBaseShader,
-      MergedOptions<Opts>
-    >;
+    interface ExtraConstructorOptions {
+      animated?: boolean | undefined | null;
+    }
 
-    /**
-     * A shorthand for the initialized type of a BooleanField class.
-     * @typeParam Opts - the options that override the default options
-     */
-    type InitializedType<Opts extends Options> = foundry.data.fields.DataField.DerivedInitializedType<
-      typeof AbstractBaseShader,
-      MergedOptions<Opts>
-    >;
-  }
+    interface LightingVisibility {
+      /** Disabled: this lighting layer is not rendered, the shaders does not decide. */
+      DISABLED: 0 & LIGHTING_VISIBILITY;
+      /** Enabled: this lighting layer is rendered normally, and the shaders can choose if they should be rendered or not. */
+      ENABLED: 1 & LIGHTING_VISIBILITY;
+      /** Required: the lighting layer is rendered, the shaders does not decide. */
+      REQUIRED: 2 & LIGHTING_VISIBILITY;
+    }
 
-  namespace VisionMode {
     type ShaderSchema = fields.SchemaField<{
       shader: ShaderField;
       uniforms: fields.ObjectField;
     }>;
 
-    type LightingSchema = fields.SchemaField<{
+    // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
+    type LightingSchema = {
       visibility: fields.NumberField;
       postProcessingModes: fields.ArrayField<fields.StringField>;
       uniforms: fields.ObjectField;
-    }>;
+    };
+
+    type LightingSchemaField = fields.SchemaField<LightingSchema>;
 
-    type LightingLevels = Record<ValueOf<typeof CONST.LIGHTING_LEVELS>, ValueOf<typeof CONST.LIGHTING_LEVELS>>;
-    type LightingMultipliers = Record<ValueOf<typeof VisionMode.LIGHTING_LEVELS>, number>;
+    type LightingLevels = Record<foundry.CONST.LIGHTING_LEVELS, foundry.CONST.LIGHTING_LEVELS>;
+    type LightingMultipliers = Record<foundry.CONST.LIGHTING_LEVELS, number>;
 
     interface Schema extends DataSchema {
       id: fields.StringField<{ blank: false }>;
@@ -159,9 +175,9 @@ declare global {
         uniforms: fields.ObjectField;
       }>;
       lighting: fields.SchemaField<{
-        background: LightingSchema;
-        coloration: LightingSchema;
-        illumination: LightingSchema;
+        background: LightingSchemaField;
+        coloration: LightingSchemaField;
+        illumination: LightingSchemaField;
         levels: fields.ObjectField<
           {
             validate: (o: unknown) => boolean;
@@ -195,22 +211,22 @@ declare global {
             required: false;
             initial: undefined;
             nullable: false;
-            min: number;
-            max: number;
+            min: -1;
+            max: 1;
           }>;
           saturation: fields.NumberField<{
             required: false;
             initial: undefined;
             nullable: false;
-            min: number;
-            max: number;
+            min: -1;
+            max: 1;
           }>;
           contrast: fields.NumberField<{
             required: false;
             initial: undefined;
             nullable: false;
-            min: number;
-            max: number;
+            min: -1;
+            max: 1;
           }>;
         }>;
         preferred: fields.BooleanField<{ initial: false }>;
diff --git a/src/foundry/client/pixi/webgl/shaders/filters/effects-masking.d.mts b/src/foundry/client/pixi/webgl/shaders/filters/effects-masking.d.mts
index 2e3960879..08dcd3ea0 100644
--- a/src/foundry/client/pixi/webgl/shaders/filters/effects-masking.d.mts
+++ b/src/foundry/client/pixi/webgl/shaders/filters/effects-masking.d.mts
@@ -105,6 +105,9 @@ declare global {
     interface Any extends AnyVisualEffectsMaskingFilter {}
     type AnyConstructor = typeof AnyVisualEffectsMaskingFilter;
 
+    type ConfiguredClass = CONFIG["Canvas"]["visualEffectsMaskingFilter"];
+    type ConfiguredInstance = FixedInstanceType<ConfiguredClass>;
+
     type PostProcessModes = Array<keyof typeof VisualEffectsMaskingFilter.POST_PROCESS_TECHNIQUES>;
 
     interface ConcreteCreateOptions {
diff --git a/src/foundry/client/pixi/webgl/shaders/filters/visibility.d.mts b/src/foundry/client/pixi/webgl/shaders/filters/visibility.d.mts
index 65d0c70b4..cf3d51c7a 100644
--- a/src/foundry/client/pixi/webgl/shaders/filters/visibility.d.mts
+++ b/src/foundry/client/pixi/webgl/shaders/filters/visibility.d.mts
@@ -60,6 +60,9 @@ declare global {
     interface Any extends AnyVisibilityFilter {}
     type AnyConstructor = typeof AnyVisibilityFilter;
 
+    type ConfiguredClass = CONFIG["Canvas"]["visibilityFilter"];
+    type ConfiguredInstance = FixedInstanceType<ConfiguredClass>;
+
     /** @internal */
     type _FragmentShaderOptions = NullishProps<{
       persistentVision: boolean;


Test patch:
diff --git a/tests/foundry/client/pixi/layers/effects/visibility.test-d.ts b/tests/foundry/client/pixi/layers/effects/visibility.test-d.ts
index ccdf59a89..7bd011532 100644
--- a/tests/foundry/client/pixi/layers/effects/visibility.test-d.ts
+++ b/tests/foundry/client/pixi/layers/effects/visibility.test-d.ts
@@ -1,11 +1,56 @@
 import { expectTypeOf } from "vitest";
-import type { ValueOf } from "fvtt-types/utils";
 
 const layer = new CanvasVisibility();
 
 expectTypeOf(layer.options.baseClass).toEqualTypeOf<typeof CanvasLayer>();
+expectTypeOf(layer.vision).toEqualTypeOf<CanvasVisionMask.CanvasVisionContainer | undefined>();
+expectTypeOf(layer.explored).toEqualTypeOf<PIXI.Container | undefined>();
+expectTypeOf(layer.visibilityOverlay).toEqualTypeOf<PIXI.Sprite | undefined>();
+expectTypeOf(layer.filter).toEqualTypeOf<VisibilityFilter.ConfiguredInstance | undefined>();
+expectTypeOf(layer.visionModeData).toEqualTypeOf<CanvasVisibility.VisionModeData>();
+expectTypeOf(layer.lightingVisibility).toEqualTypeOf<CanvasVisibility.LightingVisibility>();
+expectTypeOf(layer.lightingVisibility.background).toMatchTypeOf<VisionMode.LIGHTING_VISIBILITY>();
+
+expectTypeOf(layer.initialized).toBeBoolean();
+expectTypeOf(layer.needsContainment).toBeBoolean();
+expectTypeOf(layer.tokenVision).toBeBoolean();
+expectTypeOf(layer.textureConfiguration).toEqualTypeOf<CanvasVisibility.TextureConfiguration | undefined>();
+
+// getter not actually defined
+expectTypeOf(layer.explorationRect).toBeUndefined();
+layer.explorationRect = { x: 50, y: 100, width: 200, height: 500 };
+layer.explorationRect = undefined;
+
+expectTypeOf(layer.initializeSources()).toBeVoid();
+expectTypeOf(layer.initializeVisionMode()).toBeVoid();
+
 expectTypeOf(layer.draw()).toEqualTypeOf<Promise<CanvasVisibility>>();
+expectTypeOf(layer["_draw"]({})).toEqualTypeOf<Promise<void>>();
+
+expectTypeOf(layer.refresh()).toBeVoid();
+expectTypeOf(layer.refreshVisibility()).toBeVoid();
+expectTypeOf(layer.resetExploration()).toBeVoid();
+expectTypeOf(layer.restrictVisibility()).toBeVoid();
+
+declare const somePoint: PIXI.Point;
+declare const someToken: Token.ConfiguredInstance;
+expectTypeOf(layer.testVisibility({ x: 0, y: 0 })).toBeBoolean();
+expectTypeOf(layer.testVisibility(somePoint, {})).toBeBoolean();
+expectTypeOf(
+  layer.testVisibility(somePoint, {
+    object: someToken,
+    tolerance: 4,
+  }),
+).toBeBoolean();
 
-expectTypeOf(layer.lightingVisibility.illumination).toEqualTypeOf<ValueOf<typeof VisionMode.LIGHTING_VISIBILITY>>();
+expectTypeOf(layer["_createVisibilityTestConfig"]({ x: 0, y: 0 })).toEqualTypeOf<CanvasVisibility.TestConfig>();
+expectTypeOf(layer["_createVisibilityTestConfig"](somePoint, {})).toEqualTypeOf<CanvasVisibility.TestConfig>();
+expectTypeOf(
+  layer["_createVisibilityTestConfig"](somePoint, {
+    object: null,
+    tolerance: undefined,
+  }),
+).toEqualTypeOf<CanvasVisibility.TestConfig>();
 
-expectTypeOf(layer.testVisibility({ x: 0, y: 0 })).toEqualTypeOf<boolean>();
+// deprecated until v13
+expectTypeOf(layer.fogOverlay).toEqualTypeOf<typeof layer.visibilityOverlay>();
diff --git a/tests/foundry/client/pixi/perception/detection-mode.test-d.ts b/tests/foundry/client/pixi/perception/detection-mode.test-d.ts
index 9b1ef372a..821a32da6 100644
--- a/tests/foundry/client/pixi/perception/detection-mode.test-d.ts
+++ b/tests/foundry/client/pixi/perception/detection-mode.test-d.ts
@@ -1,19 +1,89 @@
 import { expectTypeOf } from "vitest";
-import type { ValueOf } from "fvtt-types/utils";
 
-class MyDetectionMode extends DetectionMode {}
+expectTypeOf(DetectionMode.getDetectionFilter()).toEqualTypeOf<PIXI.Filter | undefined>();
+expectTypeOf(DetectionMode.DETECTION_TYPES).toMatchTypeOf<
+  Record<keyof DetectionMode.DetectionTypes, DetectionMode.DETECTION_TYPES>
+>();
+expectTypeOf(DetectionMode.BASIC_MODE_ID).toEqualTypeOf<"basicSight">();
 
-const myDetectionMode = new MyDetectionMode({ id: "foo", label: "bar", type: DetectionMode.DETECTION_TYPES.OTHER });
+const source = {
+  id: "foo",
+  label: "bar",
+  type: DetectionMode.DETECTION_TYPES.OTHER,
+  angle: false,
+  walls: true,
+  tokenConfig: false,
+};
+const myDetectionMode = new DetectionMode(source);
 
-const myVisionSource = new VisionSource();
+declare const someVisionSource: foundry.canvas.sources.PointVisionSource;
+declare const someToken: Token.ConfiguredInstance;
+
+const someCanvasVisibilityTest = {
+  elevation: 20,
+  los: new Map([[someVisionSource, true]]),
+  point: { x: 50, y: 50 },
+};
 
 expectTypeOf(
   myDetectionMode.testVisibility(
-    myVisionSource,
+    someVisionSource,
     { id: "foobar", enabled: true, range: 3 },
-    { object: null, tests: [] },
+    { object: someToken, tests: [someCanvasVisibilityTest] },
   ),
 ).toEqualTypeOf<boolean>();
 
+expectTypeOf(myDetectionMode.id).toEqualTypeOf<string | undefined>();
+expectTypeOf(myDetectionMode.label).toEqualTypeOf<string | undefined>();
+expectTypeOf(myDetectionMode.tokenConfig).toEqualTypeOf<boolean>();
+expectTypeOf(myDetectionMode.walls).toEqualTypeOf<boolean>();
 expectTypeOf(myDetectionMode.angle).toEqualTypeOf<boolean>();
-expectTypeOf(myDetectionMode.type).toEqualTypeOf<ValueOf<typeof DetectionMode.DETECTION_TYPES>>();
+
+// @ts-expect-error For two reasons: first, this currently wants `| undefined` when it shouldn't (the field is `required: false`, but has an `initial`),
+// and second, it isn't not accepting the Branded number type
+expectTypeOf(myDetectionMode.type).toEqualTypeOf<DetectionMode.DETECTION_TYPES | null>();
+
+const someTokenDetectionMode = {
+  enabled: true,
+  id: "baz",
+  range: 600,
+};
+expectTypeOf(myDetectionMode["_canDetect"](someVisionSource, someToken)).toEqualTypeOf<boolean>();
+expectTypeOf(
+  myDetectionMode["_testPoint"](someVisionSource, someTokenDetectionMode, someToken, someCanvasVisibilityTest),
+).toEqualTypeOf<boolean>();
+expectTypeOf(
+  myDetectionMode["_testLOS"](someVisionSource, someTokenDetectionMode, someToken, someCanvasVisibilityTest),
+).toEqualTypeOf<boolean>();
+expectTypeOf(
+  myDetectionMode["_testAngle"](someVisionSource, someTokenDetectionMode, someToken, someCanvasVisibilityTest),
+).toEqualTypeOf<boolean>();
+expectTypeOf(
+  myDetectionMode["_testRange"](someVisionSource, someTokenDetectionMode, someToken, someCanvasVisibilityTest),
+).toEqualTypeOf<boolean>();
+
+const myDetectionModeLightPerception = new DetectionModeLightPerception(source);
+expectTypeOf(myDetectionModeLightPerception["_canDetect"](someVisionSource, someToken)).toEqualTypeOf<boolean>();
+expectTypeOf(
+  myDetectionModeLightPerception["_testPoint"](
+    someVisionSource,
+    someTokenDetectionMode,
+    someToken,
+    someCanvasVisibilityTest,
+  ),
+).toEqualTypeOf<boolean>();
+
+const myDetectionModeBasicSight = new DetectionModeBasicSight(source);
+expectTypeOf(myDetectionModeBasicSight["_canDetect"](someVisionSource, someToken)).toEqualTypeOf<boolean>();
+
+expectTypeOf(DetectionModeInvisibility.getDetectionFilter()).toEqualTypeOf<PIXI.Filter>();
+const myDetectionModeInvisibility = new DetectionModeInvisibility(source);
+expectTypeOf(myDetectionModeInvisibility["_canDetect"](someVisionSource, someToken)).toEqualTypeOf<boolean>();
+
+expectTypeOf(DetectionModeTremor.getDetectionFilter()).toEqualTypeOf<PIXI.Filter>();
+const myDetectionModeTremor = new DetectionModeTremor(source);
+expectTypeOf(myDetectionModeTremor["_canDetect"](someVisionSource, someToken)).toEqualTypeOf<boolean>();
+
+expectTypeOf(DetectionModeAll.getDetectionFilter()).toEqualTypeOf<PIXI.Filter>();
+const myDetectionModeAll = new DetectionModeAll(source);
+expectTypeOf(myDetectionModeAll["_canDetect"](someVisionSource, someToken)).toEqualTypeOf<boolean>();
diff --git a/tests/foundry/client/pixi/perception/fog.test-d.ts b/tests/foundry/client/pixi/perception/fog.test-d.ts
index dc8f19a28..e62c86c2f 100644
--- a/tests/foundry/client/pixi/perception/fog.test-d.ts
+++ b/tests/foundry/client/pixi/perception/fog.test-d.ts
@@ -1,5 +1,31 @@
 import { expectTypeOf } from "vitest";
 
+expectTypeOf(FogManager.COMMIT_THRESHOLD).toBeNumber();
+
+declare const someTex: PIXI.Texture;
 const myFogManager = new FogManager();
 
-expectTypeOf(myFogManager.textureConfiguration).toEqualTypeOf<FogTextureConfiguration>();
+expectTypeOf(myFogManager.exploration).toEqualTypeOf<FogExploration.ConfiguredInstance | null>();
+expectTypeOf(myFogManager.sprite).toEqualTypeOf<SpriteMesh>();
+expectTypeOf(myFogManager.extractor).toEqualTypeOf<TextureExtractor | undefined | null>();
+expectTypeOf(myFogManager.textureConfiguration).toEqualTypeOf<CanvasVisibility.TextureConfiguration | undefined>();
+
+expectTypeOf(myFogManager.initialize()).toEqualTypeOf<Promise<void>>();
+expectTypeOf(myFogManager.clear()).toEqualTypeOf<Promise<void>>();
+expectTypeOf(myFogManager.commit()).toEqualTypeOf<void>();
+expectTypeOf(myFogManager.load()).toEqualTypeOf<Promise<PIXI.Texture | void>>();
+expectTypeOf(myFogManager.reset()).toEqualTypeOf<Promise<void>>();
+expectTypeOf(myFogManager.save()).toEqualTypeOf<Promise<void>>();
+expectTypeOf(myFogManager["_handleReset"]()).toEqualTypeOf<Promise<void>>();
+
+expectTypeOf(myFogManager["_extractBase64"]()).toEqualTypeOf<Promise<string>>();
+expectTypeOf(myFogManager["_createExplorationObject"](someTex)).toEqualTypeOf<SpriteMesh>();
+expectTypeOf(
+  myFogManager["_prepareFogUpdateData"]("base64:asfasgad252345+=5236236adfa"),
+).toEqualTypeOf<FogExploration.UpdateData>();
+
+//deprecated since v11 until v13
+expectTypeOf(myFogManager.pending).toEqualTypeOf<PIXI.Container | undefined>();
+expectTypeOf(myFogManager.revealed).toEqualTypeOf<PIXI.Container | undefined>();
+expectTypeOf(myFogManager.update("garbage", true)).toEqualTypeOf<true>();
+expectTypeOf(myFogManager.resolution).toEqualTypeOf<CanvasVisibility.TextureConfiguration | undefined>();
diff --git a/tests/foundry/client/pixi/perception/vision-mode.test-d.ts b/tests/foundry/client/pixi/perception/vision-mode.test-d.ts
index a46c75e5f..e256eb833 100644
--- a/tests/foundry/client/pixi/perception/vision-mode.test-d.ts
+++ b/tests/foundry/client/pixi/perception/vision-mode.test-d.ts
@@ -1,24 +1,21 @@
 import { expectTypeOf } from "vitest";
 
-class MyVisionMode extends VisionMode {
-  _activate(source: VisionSource): void {
-    source.animate(5000);
-  }
+expectTypeOf(VisionMode.LIGHTING_VISIBILITY).toMatchTypeOf<
+  Record<keyof VisionMode.LightingVisibility, VisionMode.LIGHTING_VISIBILITY>
+>();
+expectTypeOf(VisionMode.LIGHTING_LEVELS).toEqualTypeOf<typeof foundry.CONST.LIGHTING_LEVELS>();
 
-  _deactivate(source: VisionSource): void {
-    source.animation;
-  }
-}
-
-const monochromatic = new MyVisionMode({
+const monochromatic = new VisionMode({
   id: "monochromatic",
   label: "VISION.ModeMonochromatic",
+  tokenConfig: false,
   canvas: {
     shader: ColorAdjustmentsSamplerShader,
     uniforms: { contrast: 0, saturation: -1.0, brightness: 0 },
   },
   lighting: {
     background: {
+      visibility: VisionMode.LIGHTING_VISIBILITY.DISABLED,
       postProcessingModes: ["SATURATION"],
       uniforms: { saturation: -1.0, tint: [1, 1, 1] },
     },
@@ -30,10 +27,23 @@ const monochromatic = new MyVisionMode({
       postProcessingModes: ["SATURATION"],
       uniforms: { saturation: -1.0, tint: [1, 1, 1] },
     },
+    levels: {
+      [VisionMode.LIGHTING_LEVELS.BRIGHT]: VisionMode.LIGHTING_LEVELS.HALFDARK,
+    },
   },
   vision: {
+    coloration: {
+      shader: FlameColorationShader,
+      uniforms: { saturation: -1.0, tint: [1, 1, 1] },
+    },
+    illumination: {
+      shader: null,
+      uniforms: { saturation: -1.0, tint: [1, 1, 1] },
+    },
+    background: { shader: undefined, uniforms: { saturation: -1.0, tint: [1, 1, 1] } },
     darkness: { adaptive: false },
-    defaults: { attenuation: 0, contrast: 0, saturation: -1, brightness: 0 },
+    defaults: { color: "#FFABAB", attenuation: 0, contrast: 0, saturation: -1, brightness: 0 },
+    preferred: false,
   },
 });
 
@@ -43,10 +53,13 @@ expectTypeOf(ShaderAssType).toEqualTypeOf<typeof AbstractBaseShader | undefined
 declare const ShaderInitType: ShaderField.InitializedType<ShaderField.DefaultOptions>;
 expectTypeOf(ShaderInitType).toEqualTypeOf<typeof AbstractBaseShader | undefined | null>;
 
-const myVisionSource = new VisionSource();
+declare const myVisionSource: foundry.canvas.sources.PointVisionSource.Any;
 
 // Next line could possibly be a `never` instead, but not sure the generic usage is worth the headache
 expectTypeOf(monochromatic.schema.fields.canvas.fields.shader._cast("foo")).toEqualTypeOf<typeof AbstractBaseShader>;
 expectTypeOf(monochromatic.activate(myVisionSource)).toEqualTypeOf<void>();
 expectTypeOf(monochromatic.id).toEqualTypeOf<string | undefined>();
 expectTypeOf(monochromatic.canvas.shader).toEqualTypeOf<typeof AbstractBaseShader | undefined | null>();
+expectTypeOf(monochromatic.animated).toBeBoolean();
+expectTypeOf(monochromatic.animate(0.6)).toEqualTypeOf<void>();
+expectTypeOf(monochromatic.perceivesLight).toBeBoolean();