Repository: League-of-Foundry-Developers/foundry-vtt-types
Pull request #3163 (2025-02-15 17:40:51)

dice
dice tests


Patch:
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml
index 6b47cbaa6..390cad62b 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yaml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yaml
@@ -2,7 +2,6 @@ name: Feature Request
 description: Suggest an idea for this project beyond plain Foundry types
 labels:
   - enhancement
-type: Task
 body:
   - type: input
     id: foundry-version
diff --git a/.github/ISSUE_TEMPLATE/update_class.yaml b/.github/ISSUE_TEMPLATE/update_class.yaml
index bee08dab1..1946d1909 100644
--- a/.github/ISSUE_TEMPLATE/update_class.yaml
+++ b/.github/ISSUE_TEMPLATE/update_class.yaml
@@ -3,7 +3,6 @@ description: Submit an issue for updating a class for a certain Foundry VTT vers
 title: "Update CLASS to Foundry VTT VERSION"
 labels:
   - version update
-type: Feature
 body:
   - type: input
     id: class
diff --git a/.github/ISSUE_TEMPLATE/update_for_v13.yaml b/.github/ISSUE_TEMPLATE/update_for_v12.yaml
similarity index 85%
rename from .github/ISSUE_TEMPLATE/update_for_v13.yaml
rename to .github/ISSUE_TEMPLATE/update_for_v12.yaml
index 8caeb086e..f9492f291 100644
--- a/.github/ISSUE_TEMPLATE/update_for_v13.yaml
+++ b/.github/ISSUE_TEMPLATE/update_for_v12.yaml
@@ -1,10 +1,9 @@
-name: Update for v13
-description: Submit an issue for adding, updating or deleting something for Foundry VTT v13
-title: Update … for Foundry VTT v13.336
+name: Update for v12
+description: Submit an issue for adding, updating or deleting something for Foundry VTT v12
+title: Update … for Foundry VTT v12.327
 labels:
   - version update
-  - foundry v13
-type: Feature
+  - foundry v12
 body:
   - type: input
     id: to-change
diff --git a/.github/ISSUE_TEMPLATE/wrong_type.yaml b/.github/ISSUE_TEMPLATE/wrong_type.yaml
index f6ba99813..9f1887a87 100644
--- a/.github/ISSUE_TEMPLATE/wrong_type.yaml
+++ b/.github/ISSUE_TEMPLATE/wrong_type.yaml
@@ -2,7 +2,6 @@ name: Wrong Type
 description: Report an incorrect type to help us improve
 labels:
   - bug
-type: Bug
 body:
   - type: input
     id: foundry-version
diff --git a/src/foundry/client-esm/dice/parser.d.mts b/src/foundry/client-esm/dice/parser.d.mts
index 65e9ed8a7..6b4eac1b2 100644
--- a/src/foundry/client-esm/dice/parser.d.mts
+++ b/src/foundry/client-esm/dice/parser.d.mts
@@ -44,8 +44,6 @@ declare class RollParser {
     error: (error: string) => void,
   ): RollParseNode;
 
-  /* -------------------------------------------- */
-
   /**
    * Handle a dice term.
    * @param number - The number of dice.
@@ -64,8 +62,6 @@ declare class RollParser {
     formula: string,
   ): DiceRollParseNode;
 
-  /* -------------------------------------------- */
-
   /**
    * Handle a numeric term.
    * @param number - The number.
@@ -74,8 +70,6 @@ declare class RollParser {
    */
   protected _onNumericTerm(number: number, flavor: string): NumericRollParseNode;
 
-  /* -------------------------------------------- */
-
   /**
    * Handle a math term.
    * @param fn - The Math function.
@@ -93,8 +87,6 @@ declare class RollParser {
     formula: string,
   ): FunctionRollParseNode;
 
-  /* -------------------------------------------- */
-
   /**
    * Handle a pool term.
    * @param head - The first term.
@@ -112,8 +104,6 @@ declare class RollParser {
     formula: string,
   ): PoolRollParseNode;
 
-  /* -------------------------------------------- */
-
   /**
    * Handle a parenthetical.
    * @param term - The inner term.
@@ -123,8 +113,6 @@ declare class RollParser {
    */
   protected _onParenthetical(term: RollParseNode, flavor: string | null, formula: string): ParentheticalRollParseNode;
 
-  /* -------------------------------------------- */
-
   /**
    * Handle some string that failed to be classified.
    * @param term - The term.
@@ -132,16 +120,12 @@ declare class RollParser {
    */
   protected _onStringTerm(term: string, flavor: string | null): StringParseNode;
 
-  /* -------------------------------------------- */
-
   /**
    * Collapse multiple additive operators into a single one.
    * @param operators - A sequence of additive operators.
    */
   protected _collapseOperators(operators: string[]): string;
 
-  /* -------------------------------------------- */
-
   /**
    * Wrap a term with a leading minus.
    * @param term - The term to wrap.
@@ -157,8 +141,6 @@ declare class RollParser {
    */
   static flattenTree(root: RollParseNode): RollParseNode[];
 
-  /* -------------------------------------------- */
-
   /**
    * Use the Shunting Yard algorithm to convert a parse tree or list of terms into an AST with correct operator
    * precedence.
@@ -167,12 +149,10 @@ declare class RollParser {
    */
   static toAST(root: RollParseNode | RollTerm[]): RollParseNode;
 
-  /* -------------------------------------------- */
-
   /**
    * Determine if a given node is an operator term.
    */
-  static isOperatorTerm(node: RollParseNode | RollTerm): void;
+  static isOperatorTerm(node: RollParseNode | RollTerm): boolean;
 
   /* -------------------------------------------- */
   /*  Debug Formatting                            */
@@ -184,16 +164,12 @@ declare class RollParser {
    */
   static formatList(list: RollParseArg[]): string;
 
-  /* -------------------------------------------- */
-
   /**
    * Format a parser argument.
    * @param arg - The argument.
    */
   static formatArg(arg: RollParseArg): string;
 
-  /* -------------------------------------------- */
-
   /**
    * Format arguments for debugging.
    * @param method - The method name.
diff --git a/src/foundry/client-esm/dice/roll.d.mts b/src/foundry/client-esm/dice/roll.d.mts
index 7c9239f63..1623db626 100644
--- a/src/foundry/client-esm/dice/roll.d.mts
+++ b/src/foundry/client-esm/dice/roll.d.mts
@@ -1,4 +1,4 @@
-import type { AnyObject, InexactPartial, FixedInstanceType, IntentionalPartial } from "fvtt-types/utils";
+import type { AnyObject, InexactPartial, FixedInstanceType, IntentionalPartial, EmptyObject } from "fvtt-types/utils";
 import type { RollParseNode } from "./_types.d.mts";
 import type DiceTerm from "./terms/dice.d.mts";
 import type PoolTerm from "./terms/pool.d.mts";
@@ -28,14 +28,14 @@ import type RollResolver from "../applications/dice/roll-resolver.d.mts";
  * console.log(r.total);    // 22
  * ```
  */
-declare class Roll<D extends AnyObject = AnyObject> {
+declare class Roll<D extends AnyObject = EmptyObject> {
   /**
    * @param formula - The string formula to parse
    * @param data    - The data object against which to parse attributes within the formula
    *                  (default: `{}`)
    * @param options - (default: `{}`)
    */
-  constructor(formula: string, data?: D, options?: Roll["options"]);
+  constructor(formula: string, data?: D, options?: Roll.Options);
 
   /**
    * The original provided data object which substitutes into attributes of the roll formula
@@ -45,7 +45,7 @@ declare class Roll<D extends AnyObject = AnyObject> {
   /**
    * Options which modify or describe the Roll
    */
-  options: InexactPartial<Roll.Options>;
+  options: Roll.Options;
 
   /**
    * The identified terms of the Roll
@@ -106,8 +106,6 @@ declare class Roll<D extends AnyObject = AnyObject> {
    */
   static RESOLVERS: Map<Roll, RollResolver>; // TODO: Fix this
 
-  /* -------------------------------------------- */
-
   /**
    * Prepare the data structure used for the Roll.
    * This is factored out to allow for custom Roll classes to do special data preparation using provided input.
@@ -167,8 +165,6 @@ declare class Roll<D extends AnyObject = AnyObject> {
    */
   clone(): this;
 
-  /* -------------------------------------------- */
-
   /**
    * Execute the Roll, replacing dice and evaluating the total result
    * @param options - Options which inform how the Roll is evaluated
@@ -189,9 +185,7 @@ declare class Roll<D extends AnyObject = AnyObject> {
     allowStrings,
     allowInteractive,
     ...options
-  }?: InexactPartial<Roll.Options>): Promise<Roll.Evaluated<this>>;
-
-  /* -------------------------------------------- */
+  }?: Roll.Options): Promise<Roll.Evaluated<this>>;
 
   /**
    * Execute the Roll synchronously, replacing dice and evaluating the total result.
@@ -200,7 +194,7 @@ declare class Roll<D extends AnyObject = AnyObject> {
    *
    * @returns The evaluated Roll instance.
    */
-  evaluateSync({ minimize, maximize, allowStrings, strict }?: InexactPartial<Roll.Options>): Roll.Evaluated<this>;
+  evaluateSync({ minimize, maximize, allowStrings, strict }?: Roll.Options): Roll.Evaluated<this>;
 
   /**
    * Evaluate the roll asynchronously.
@@ -208,9 +202,7 @@ declare class Roll<D extends AnyObject = AnyObject> {
    * @param options - Options which inform how evaluation is performed
    * @internal
    */
-  protected _evaluate(options?: InexactPartial<Roll.Options>): Promise<Roll.Evaluated<this>>;
-
-  /* -------------------------------------------- */
+  protected _evaluate(options?: Roll.Options): Promise<Roll.Evaluated<this>>;
 
   /**
    * Evaluate an AST asynchronously.
@@ -218,21 +210,14 @@ declare class Roll<D extends AnyObject = AnyObject> {
    * @param options - Options which inform how evaluation is performed
    *                  (default: `{}`)
    */
-  protected _evaluateASTAsync(
-    node: RollParseNode | RollTerm,
-    options?: InexactPartial<Roll.Options>,
-  ): Promise<string | number>;
-
-  /* -------------------------------------------- */
+  protected _evaluateASTAsync(node: RollParseNode | RollTerm, options?: Roll.Options): Promise<string | number>;
 
   /**
    * Evaluate the roll synchronously.
    * @param options - Options which inform how evaluation is performed
    *                  (default: `{}`)
    */
-  protected _evaluateSync(options?: InexactPartial<Roll.Options>): Roll.Evaluated<this>;
-
-  /* -------------------------------------------- */
+  protected _evaluateSync(options?: Roll.Options): Roll.Evaluated<this>;
 
   /**
    * Evaluate an AST synchronously.
@@ -240,9 +225,7 @@ declare class Roll<D extends AnyObject = AnyObject> {
    * @param options - Options which inform how evaluation is performed
    *                  (default: `{}`)
    */
-  protected _evaluateASTSync(node: RollParseNode | RollTerm, options?: InexactPartial<Roll.Options>): string | number;
-
-  /* -------------------------------------------- */
+  protected _evaluateASTSync(node: RollParseNode | RollTerm, options?: Roll.Options): string | number;
 
   /**
    * Safely evaluate the final total result for the Roll using its component terms.
@@ -250,16 +233,12 @@ declare class Roll<D extends AnyObject = AnyObject> {
    */
   protected _evaluateTotal(): number;
 
-  /* -------------------------------------------- */
-
   /**
    * Alias for evaluate.
    * @see Roll#evaluate
    * @param options - Options passed to Roll#evaluate.
    */
-  roll(options?: InexactPartial<Roll.Options>): Promise<Roll.Evaluated<this>>;
-
-  /* -------------------------------------------- */
+  roll(options?: Roll.Options): Promise<Roll.Evaluated<this>>;
 
   /**
    * Create a new Roll object using the original provided formula and data.
@@ -267,9 +246,7 @@ declare class Roll<D extends AnyObject = AnyObject> {
    * @param options - Evaluation options passed to Roll#evaluate
    * @returns A new Roll object, rolled using the same formula and data
    */
-  reroll(options?: InexactPartial<Roll.Options>): Promise<Roll.Evaluated<this>>;
-
-  /* -------------------------------------------- */
+  reroll(options?: Roll.Options): Promise<Roll.Evaluated<this>>;
 
   /**
    * Recompile the formula string that represents this Roll instance from its component terms.
@@ -277,16 +254,12 @@ declare class Roll<D extends AnyObject = AnyObject> {
    */
   resetFormula(): string;
 
-  /* -------------------------------------------- */
-
   /**
    * Propagate flavor text across all terms that do not have any.
    * @param flavor -The flavor text.
    */
   propagateFlavor(flavor: string): void;
 
-  /* -------------------------------------------- */
-
   /** @override */
   toString(): string;
 
@@ -302,10 +275,10 @@ declare class Roll<D extends AnyObject = AnyObject> {
    * @param options - Additional options which modify or describe this Roll
    * @returns The constructed Roll instance
    */
-  static create<D extends AnyObject = AnyObject>(
+  static create<D extends AnyObject = EmptyObject>(
     formula: string,
     data?: D,
-    options?: InexactPartial<Roll.Options>,
+    options?: Roll.Options,
   ): typeof CONFIG.Dice.rolls extends [infer T] ? T : Roll<D>;
 
   /**
@@ -370,8 +343,6 @@ declare class Roll<D extends AnyObject = AnyObject> {
    */
   static parse(formula: string, data: Record<string, unknown>): RollTerm[];
 
-  /* -------------------------------------------- */
-
   /**
    * Instantiate the nodes in an AST sub-tree into RollTerm instances.
    * @param ast - The root of the AST sub-tree.
@@ -421,19 +392,11 @@ declare class Roll<D extends AnyObject = AnyObject> {
    * @param term         - A remaining un-classified string
    * @param options      - Options which customize classification
    *                       (default: `{}`)
-   * @param intermediate - Allow intermediate terms
-   *                       (default: `true`)
-   * @param prior        - The prior classified term
-   * @param next         - The next term to classify
    * @returns A classified RollTerm instance
    */
-  protected static _classifyStringTerm(
+  static _classifyStringTerm(
     term: string,
-    {
-      intermediate,
-      prior,
-      next,
-    }?: InexactPartial<{ intermediate: boolean; prior: RollTerm | string; next: RollTerm | string }>,
+    options?: Roll.ClassifyStringTermOptions, // not: null (destructured)
   ): RollTerm;
 
   /* -------------------------------------------- */
@@ -489,10 +452,13 @@ declare class Roll<D extends AnyObject = AnyObject> {
    * @returns A promise which resolves to the created ChatMessage entity, if create is true
    *          or the Object of prepared chatData otherwise.
    */
-  toMessage<const Create extends boolean | null | undefined>(
-    messageData?: Roll.MessageData,
-    options?: Roll.ToMessageOptions<Create>,
-  ): Promise<Roll.ToMessageReturn<Create>>;
+  toMessage<
+    const Create extends boolean | null | undefined,
+    ConcreteMessageData extends Roll.MessageData | null | undefined = undefined,
+  >(
+    messageData?: ConcreteMessageData,
+    options?: Roll.ToMessageOptions<Create>, // can't be null because it gets destructured
+  ): Promise<Roll.ToMessageReturn<Create, ConcreteMessageData>>;
 
   /* -------------------------------------------- */
   /*  Interface Helpers                           */
@@ -543,7 +509,7 @@ declare class Roll<D extends AnyObject = AnyObject> {
    * @param json - Serialized JSON data representing the Roll
    * @returns A reconstructed Roll instance
    */
-  static fromJSON(json: string): Roll;
+  static fromJSON<T extends Roll.AnyConstructor>(this: T, json: string): FixedInstanceType<T>;
 
   /**
    * Manually construct a Roll object by providing an explicit set of input terms
@@ -563,7 +529,7 @@ declare class Roll<D extends AnyObject = AnyObject> {
   static fromTerms<T extends Roll.AnyConstructor>(
     this: T,
     terms: RollTerm[],
-    options?: InexactPartial<Roll.Options>,
+    options?: Roll.Options,
   ): FixedInstanceType<T>;
 }
 
@@ -571,7 +537,7 @@ declare namespace Roll {
   type Any = Roll<any>;
   type AnyConstructor = typeof AnyRoll;
 
-  interface Options extends RollTerm.EvaluationOptions {
+  interface _Options extends RollTerm.EvaluationOptions {
     /**
      * If false, force the use of non-interactive rolls and do not prompt the user to make manual rolls.
      * @defaultValue `true`
@@ -584,6 +550,8 @@ declare namespace Roll {
     strict?: boolean | undefined;
   }
 
+  interface Options extends InexactPartial<_Options> {}
+
   interface SplitGroupOptions {
     openRegexp: RegExp | string;
     closeRegexp: RegExp | string;
@@ -620,11 +588,26 @@ declare namespace Roll {
     total: number | null;
   }
 
+  type _ClassifyStringTermOptions = InexactPartial<{
+    /** Allow intermediate terms
+     *  @defaultValue true
+     */
+    intermediate: boolean; // not: null (default true)
+
+    /** The prior classified term */
+    prior: RollTerm | string | null;
+
+    /** The next term to classify */
+    next: RollTerm | string | null;
+  }>;
+
+  interface ClassifyStringTermOptions extends _ClassifyStringTermOptions {}
+
   // TODO(LukeAbby): When shims are added then `"user"` should also be added here #3065. Specifically `user` should be added as partial.
   // Also use `IntentionalPartial<ChatMessageCreateData, "content" | "sound" | "rolls">` once `documents-v2` is merged.
   //
   // This is `IntentionalPartial` because Foundry merges in defaults with `mergeObject`.
-  interface MessageData
+  interface _MessageData
     extends Omit<ChatMessageCreateData, "content" | "sound" | "rolls">,
       IntentionalPartial<Pick<ChatMessageCreateData, "content" | "sound" | "rolls">> {
     /**
@@ -648,7 +631,9 @@ declare namespace Roll {
     rolls?: ChatMessageCreateData["rolls"];
   }
 
-  type Evaluated<T extends Roll> = T & { _evaluated: true; _total: number; get total(): number };
+  interface MessageData extends InexactPartial<_MessageData> {}
+
+  type Evaluated<T extends Roll<any>> = T & { _evaluated: true; _total: number; get total(): number };
 
   interface ToMessageOptions<Create extends boolean | null | undefined> {
     /**
@@ -664,7 +649,11 @@ declare namespace Roll {
     create?: Create;
   }
 
-  type ToMessageReturn<Create extends boolean | null | undefined> =
+  type ToMessageReturn<
+    Create extends boolean | null | undefined,
+    ConcreteMessageData extends Roll.MessageData | null | undefined = undefined,
+  > =
+    | (ConcreteMessageData extends undefined ? ChatMessage.ConfiguredInstance | undefined : never)
     | (Create extends true | undefined ? ChatMessage.ConfiguredInstance | undefined : never)
     | (Create extends false | null ? ChatMessageCreateData : never);
 }
diff --git a/src/foundry/client-esm/dice/terms/coin.d.mts b/src/foundry/client-esm/dice/terms/coin.d.mts
index 93c949b6f..0f3e6b3c5 100644
--- a/src/foundry/client-esm/dice/terms/coin.d.mts
+++ b/src/foundry/client-esm/dice/terms/coin.d.mts
@@ -24,8 +24,6 @@ declare class Coin extends DiceTerm {
    */
   static MODIFIERS: Coin.Modifiers;
 
-  /* -------------------------------------------- */
-
   override roll({
     minimize,
     maximize,
@@ -36,8 +34,6 @@ declare class Coin extends DiceTerm {
 
   override getResultCSS(result: DiceTerm.Result): (string | null)[];
 
-  /* -------------------------------------------- */
-
   override mapRandomFace(randomUniform: number): number;
 
   /* -------------------------------------------- */
diff --git a/src/foundry/client-esm/dice/terms/dice.d.mts b/src/foundry/client-esm/dice/terms/dice.d.mts
index 7b92b4428..8742de79f 100644
--- a/src/foundry/client-esm/dice/terms/dice.d.mts
+++ b/src/foundry/client-esm/dice/terms/dice.d.mts
@@ -24,20 +24,16 @@ declare abstract class DiceTerm extends RollTerm {
    */
   constructor(termData?: InexactPartial<DiceTerm.TermData>);
 
-  get method(): string; // TODO: Convert to CONFIG.Dice.fulfillment.methods
+  get method(): keyof typeof CONFIG.Dice.fulfillment.methods | null | undefined;
 
-  set method(method: string); // TODO: Convert to CONFIG.Dice.fulfillment.methods
-
-  #method: string; // TODO: Convert to CONFIG.Dice.fulfillment.methods
+  set method(method: keyof typeof CONFIG.Dice.fulfillment.methods);
 
   /**  An Array of dice term modifiers which are applied. */
-  modifiers: DiceTerm.TermData["modifiers"];
+  modifiers: string[];
 
   /** The array of dice term results which have been rolled. */
   results: DiceTerm.Result[];
 
-  /* -------------------------------------------- */
-
   /**
    * Define the denomination string used to register this DiceTerm type in CONFIG.Dice.terms
    * @defaultValue ""
@@ -73,27 +69,26 @@ declare abstract class DiceTerm extends RollTerm {
   /** The number of dice of this term to roll. Returns undefined if the number is a
    * complex term that has not yet been evaluated.
    */
-  get number(): DiceTerm.TermData["number"] | undefined;
+  get number(): number | undefined;
   /** The number of dice of this term to roll. */
-  set number(value: DiceTerm.TermData["number"]);
+  set number(value: number);
 
   /**
    * The number of dice of this term to roll, before modifiers are applied, or a Roll instance that will be evaluated to
    * a number.
    */
-  _number: DiceTerm.TermData["number"] | Roll;
+  _number: number | Roll;
 
   /**
    * The number of faces on the die. Returns undefined if the faces are represented as a complex term that has not yet
    * been evaluated.
    */
-  get faces(): DiceTerm.TermData["faces"] | undefined;
-  set faces(value: DiceTerm.TermData["faces"]);
+  get faces(): number | undefined;
+  set faces(value: number);
 
   /** The number of faces on the die, or a Roll instance that will be evaluated to a number. */
-  _faces: DiceTerm.TermData["faces"] | Roll;
+  _faces: number | Roll;
 
-  /* -------------------------------------------- */
   /**  The denomination of this DiceTerm instance. */
   get denomination(): string;
 
@@ -119,27 +114,20 @@ declare abstract class DiceTerm extends RollTerm {
    */
   alter(multiply: number, add: number): this;
 
-  /* -------------------------------------------- */
-
   protected _evaluate(options?: InexactPartial<DiceTerm.EvaluationOptions>): this | Promise<this>;
 
-  /* -------------------------------------------- */
-
   /**
    * Evaluate this dice term asynchronously.
    * @param options - Options forwarded to inner Roll evaluation. (Default: `{}`)
    */
   _evaluateAsync(options?: InexactPartial<DiceTerm.EvaluationOptions>): Promise<this>;
 
-  /* -------------------------------------------- */
   /**
    * Evaluate deterministic values of this term synchronously.
    * @param options - Options forwarded to inner Roll evaluation. (Default: `{}`)
    */
   _evaluateSync(options?: InexactPartial<DiceTerm.EvaluationOptions>): this;
 
-  /* -------------------------------------------- */
-
   /**
    * Roll the DiceTerm by mapping a random uniform draw against the faces of the dice term.
    * @param minimize - Minimize the result, obtaining the smallest possible value.
@@ -148,8 +136,6 @@ declare abstract class DiceTerm extends RollTerm {
    */
   roll({ minimize, maximize, ...options }?: InexactPartial<DiceTerm.EvaluationOptions>): Promise<DiceTerm.Result>;
 
-  /* -------------------------------------------- */
-
   /**
    * Generate a roll result value for this DiceTerm based on its fulfillment method.
    * @param  options - Options forwarded to the fulfillment method handler.
@@ -158,8 +144,6 @@ declare abstract class DiceTerm extends RollTerm {
    */
   protected _roll(options?: InexactPartial<DiceTerm.EvaluationOptions>): Promise<number | undefined>;
 
-  /* -------------------------------------------- */
-
   /**
    * Invoke the configured fulfillment handler for this term to produce a result value.
    * @param options -Options forwarded to the fulfillment method handler.
@@ -168,8 +152,6 @@ declare abstract class DiceTerm extends RollTerm {
    */
   #invokeFulfillmentHandler(options?: InexactPartial<DiceTerm.EvaluationOptions>): Promise<number | undefined>;
 
-  /* -------------------------------------------- */
-
   /**
    * Maps a randomly-generated value in the interval [0, 1) to a face value on the die.
    * @param randomUniform - A value to map. Must be in the interval [0, 1).
@@ -177,8 +159,6 @@ declare abstract class DiceTerm extends RollTerm {
    */
   mapRandomFace(randomUniform: number): number;
 
-  /* -------------------------------------------- */
-
   /** Generate a random face value for this die using the configured PRNG. */
   randomFace(): number;
 
@@ -189,8 +169,6 @@ declare abstract class DiceTerm extends RollTerm {
    */
   getResultLabel(result: DiceTerm.Result): string;
 
-  /* -------------------------------------------- */
-
   /**
    * Get the CSS classes that should be used to display each rolled result
    * @param result - The rolled result
@@ -198,8 +176,6 @@ declare abstract class DiceTerm extends RollTerm {
    */
   getResultCSS(result: DiceTerm.Result): (string | null)[];
 
-  /* -------------------------------------------- */
-
   /**
    * Render the tooltip HTML for a Roll instance
    * @returns The data object used to render the default tooltip template for this DiceTerm
@@ -216,15 +192,12 @@ declare abstract class DiceTerm extends RollTerm {
    */
   protected _evaluateModifiers(): void;
 
-  /* -------------------------------------------- */
-
   /**
    * Evaluate a single modifier command, recording it in the array of evaluated modifiers
    * @param command - The parsed modifier command
    * @param modifier -  The full modifier request
    */
   protected _evaluateModifier(command: string, modifier: string): void;
-  /* -------------------------------------------- */
 
   /**
    * A helper comparison function.
@@ -236,50 +209,36 @@ declare abstract class DiceTerm extends RollTerm {
    */
   static compareResult(result: number, comparison: string, target: number): boolean;
 
-  /* -------------------------------------------- */
-
   /**
    * A helper method to modify the results array of a dice term by flagging certain results are kept or dropped.
    * @param results - The results array
    * @param number  - The number to keep or drop
-   * @param keep    - Keep results?
-   *                  (default: `true`)
-   * @param highest - Keep the highest?
-   *                  (default: `true`)
    * @returns The modified results array
    */
   protected static _keepOrDrop(
     results: DiceTerm.Result[],
     number: number,
-    { keep, highest }?: InexactPartial<{ keep: boolean; highest: boolean }>,
+    options?: DiceTerm.KeepOrDropOptions,
   ): DiceTerm.Result;
 
-  /* -------------------------------------------- */
-
   /**
    * A reusable helper function to handle the identification and deduction of failures
-   * @param flagFailure - (default: `false`)
-   * @param flagSuccess - (default: `false`)
    */
   protected static _applyCount(
     results: DiceTerm.Result[],
     comparison: string,
     target: number,
-    { flagSuccess, flagFailure }?: InexactPartial<{ flagSuccess: boolean; flagFailure: boolean }>,
+    options?: DiceTerm.ApplyCountOptions, // not: null (destructured)
   ): void;
 
-  /* -------------------------------------------- */
-
   /**
    * A reusable helper function to handle the identification and deduction of failures
-   * @param deductFailure - (default: `false`)
-   * @param invertFailure - (default: `false`)
    */
   protected static _applyDeduct(
     results: DiceTerm.Result[],
     comparison: string,
     target: number,
-    { deductFailure, invertFailure }?: InexactPartial<{ deductFailure: boolean; invertFailure: boolean }>,
+    options?: DiceTerm.ApplyDeductOptions, // not: null (destructured)
   ): void;
 
   /* -------------------------------------------- */
@@ -290,16 +249,12 @@ declare abstract class DiceTerm extends RollTerm {
    * Determine whether a string expression matches this type of term
    * @param expression - The expression to parse
    * @param options - Additional options which customize the match
-   * @param imputeNumber - Allow the number of dice to be optional, i.e. "d6"
-   *                       (default: `true`)
    */
   static matchTerm(
     expression: string,
-    { imputeNumber }?: InexactPartial<{ imputeNumber: boolean }>,
+    options?: DiceTerm.MatchTermOptions, // not: null (destructured)
   ): RegExpMatchArray | null;
 
-  /* -------------------------------------------- */
-
   /**
    * Construct a term of this type given a matched regular expression array.
    * @param match - The matched regular expression array
@@ -307,7 +262,6 @@ declare abstract class DiceTerm extends RollTerm {
    */
   static fromMatch(match: RegExpMatchArray): DiceTerm;
 
-  /* -------------------------------------------- */
   /** Construct a DiceTerm from parser information. */
   static override fromParseNode(node: DiceRollParseNode): DiceTerm;
 
@@ -332,11 +286,35 @@ declare namespace DiceTerm {
   }
 
   interface TermData {
+    /**
+     * @defaultValue `1`
+     */
     number: number;
+
+    /**
+     * @defaultValue `6`
+     */
     faces: number;
+
+    /**
+     * @defaultValue `undefined`
+     */
+    method: keyof typeof CONFIG.Dice.fulfillment.methods | null | undefined;
+
+    /**
+     * @defaultValue `[]`
+     */
     modifiers: string[];
+
+    /**
+     * @defaultValue `[]`
+     */
     results: Result[];
-    options: DiceTerm.Options;
+
+    /**
+     * @defaultValue `{}`
+     */
+    options: InexactPartial<DiceTerm.Options>;
   }
 
   interface Options extends RollTerm.Options {}
@@ -370,6 +348,48 @@ declare namespace DiceTerm {
     rolls: { result: string; classes: string }[];
   }
 
+  type _KeepOrDropOptions = InexactPartial<{
+    /** Keep results?
+     * @defaultValue true
+     */
+    keep?: boolean | undefined; // not: null (function checks keep===highest)
+    /** Keep the highest?
+     * @defaultValue true
+     */
+    highest?: boolean | undefined; // not: null (function checks keep===highest)
+  }>;
+
+  interface KeepOrDropOptions extends _KeepOrDropOptions {}
+
+  type _ApplyCountOptions = InexactPartial<{
+    /** @defaultValue false */
+    flagSuccess: boolean | null;
+
+    /** @defaultValue false */
+    flagFailure: boolean | null;
+  }>;
+
+  interface ApplyCountOptions extends _ApplyCountOptions {}
+
+  type _ApplyDeductOptions = InexactPartial<{
+    /** @defaultValue false */
+    deductFailure: boolean | null;
+
+    /** @defaultValue false */
+    invertFailure: boolean | null;
+  }>;
+
+  interface ApplyDeductOptions extends _ApplyDeductOptions {}
+
+  type _MatchTermOptions = InexactPartial<{
+    /** Allow the number of dice to be optional, i.e. "d6"
+     * @defaultValue true
+     */
+    imputeNumber: boolean | null;
+  }>;
+
+  interface MatchTermOptions extends _MatchTermOptions {}
+
   interface EvaluationOptions extends RollTerm.EvaluationOptions {
     /**
      * Throw an error if attempting to evaluate a die term in a way that cannot be done
diff --git a/src/foundry/client-esm/dice/terms/die.d.mts b/src/foundry/client-esm/dice/terms/die.d.mts
index 20b945ad3..a394e34fe 100644
--- a/src/foundry/client-esm/dice/terms/die.d.mts
+++ b/src/foundry/client-esm/dice/terms/die.d.mts
@@ -215,7 +215,7 @@ declare namespace Die {
   type AnyConstructor = typeof AnyDie;
 
   interface TermData extends DiceTerm.TermData {
-    modifiers: Array<keyof typeof Die.MODIFIERS>;
+    modifiers: Array<keyof Modifiers>;
   }
 
   interface Modifiers {
diff --git a/src/foundry/client-esm/dice/terms/fate.d.mts b/src/foundry/client-esm/dice/terms/fate.d.mts
index c09e66f6e..0696b7e09 100644
--- a/src/foundry/client-esm/dice/terms/fate.d.mts
+++ b/src/foundry/client-esm/dice/terms/fate.d.mts
@@ -35,7 +35,7 @@ declare namespace FateDie {
   type AnyConstructor = typeof AnyFateDie;
 
   interface TermData extends DiceTerm.TermData {
-    modifiers: Array<keyof typeof FateDie.MODIFIERS>;
+    modifiers: Array<keyof Modifiers>;
   }
 
   interface Modifiers {
diff --git a/src/foundry/client-esm/dice/terms/function.d.mts b/src/foundry/client-esm/dice/terms/function.d.mts
index 2e98c5d7f..467a362f1 100644
--- a/src/foundry/client-esm/dice/terms/function.d.mts
+++ b/src/foundry/client-esm/dice/terms/function.d.mts
@@ -8,19 +8,19 @@ import type DiceTerm from "./dice.d.mts";
  * A type of RollTerm used to apply a function.
  */
 declare class FunctionTerm extends RollTerm {
-  constructor(termData?: InexactPartial<FunctionTerm.TermData>);
+  constructor(termData: FunctionTerm.TermData);
 
-  /* The name of the configured function, or one in the Math environment, which should be applied to the term. */
+  /** The name of the configured function, or one in the Math environment, which should be applied to the term. **/
   fn: string;
 
   /** An array of string argument terms for the function. */
   terms: string[];
 
-  /* The cached Roll instances for each function argument. */
+  /** The cached Roll instances for each function argument. **/
   rolls: Roll[];
 
-  /* The cached result of evaluating the method arguments. */
-  result: string | number;
+  /** The cached result of evaluating the method arguments. **/
+  result: string | number | undefined; // note: it will be undefined if the function has not yet been evaluated
 
   /** Is this term intermediate, and should be evaluated first as part of the simplification process? */
   override isIntermediate: true;
@@ -59,8 +59,6 @@ declare class FunctionTerm extends RollTerm {
    */
   protected _evaluateSync(options?: InexactPartial<DiceTerm.EvaluationOptions>): this;
 
-  /* -------------------------------------------- */
-
   /**
    * Parse a function argument from its evaluated Roll instance.
    * @param roll - The evaluated Roll instance that wraps the argument.
@@ -75,28 +73,27 @@ declare class FunctionTerm extends RollTerm {
     data: Record<string, unknown>,
   ): FixedInstanceType<T>;
 
-  /* -------------------------------------------- */
   override toJSON(): Record<string, unknown>;
 
-  /* -------------------------------------------- */
   static override fromParseNode(node: FunctionRollParseNode): RollTerm;
 }
 
 declare namespace FunctionTerm {
-  interface Data extends InexactPartial<TermData> {
+  interface Data extends TermData {
+    fn: string;
     class: string | undefined;
     evaluated: boolean;
   }
 
   interface TermData {
-    /* The name of the configured function, or one in the Math environment, which should be applied to the term. */
+    /** The name of the configured function, or one in the Math environment, which should be applied to the term. */
     fn: string;
     /** An array of string argument terms for the function. */
-    terms: string[];
-    /* The cached Roll instances for each function argument. */
-    rolls: Roll[];
-    /* The cached result of evaluating the method arguments. */
-    result: string | number;
+    terms?: string[] | undefined;
+    /** The cached Roll instances for each function argument. */
+    rolls?: Roll[] | undefined;
+    /** The cached result of evaluating the method arguments. */
+    result?: string | number | undefined;
     options?: InexactPartial<FunctionTerm.Options>;
   }
 
diff --git a/src/foundry/client-esm/dice/terms/numeric.d.mts b/src/foundry/client-esm/dice/terms/numeric.d.mts
index 34c365c0b..a57b1e0ed 100644
--- a/src/foundry/client-esm/dice/terms/numeric.d.mts
+++ b/src/foundry/client-esm/dice/terms/numeric.d.mts
@@ -5,7 +5,7 @@ import type RollTerm from "./term.d.mts";
  * A type of RollTerm used to represent static numbers.
  */
 declare class NumericTerm extends RollTerm {
-  constructor({ number, options }: NumericTerm.TermData);
+  constructor(termData: NumericTerm.TermData);
 
   number: NumericTerm.TermData["number"];
 
@@ -32,8 +32,6 @@ declare class NumericTerm extends RollTerm {
    */
   static matchTerm(expression: string): RegExpMatchArray | null;
 
-  /* -------------------------------------------- */
-
   /**
    * Construct a term of this type given a matched regular expression array.
    * @param match -  The matched regular expression array
@@ -47,7 +45,7 @@ declare namespace NumericTerm {
     number: number;
 
     /**
-     * @defaultValue `{}`
+     * @defaultValue `undefined`
      */
     options?: InexactPartial<RollTerm.Options>;
   }
diff --git a/src/foundry/client-esm/dice/terms/operator.d.mts b/src/foundry/client-esm/dice/terms/operator.d.mts
index 3257d18ef..d5b0ac418 100644
--- a/src/foundry/client-esm/dice/terms/operator.d.mts
+++ b/src/foundry/client-esm/dice/terms/operator.d.mts
@@ -6,7 +6,7 @@ import type RollTerm from "./term.d.mts";
  * A type of RollTerm used to denote and perform an arithmetic operation.
  */
 declare class OperatorTerm extends RollTerm {
-  constructor({ operator, options }?: InexactPartial<OperatorTerm.TermData>);
+  constructor(termData: OperatorTerm.TermData);
 
   /** The term's operator value. */
   operator: OperatorTerm.TermData["operator"];
diff --git a/src/foundry/client-esm/dice/terms/parenthetical.d.mts b/src/foundry/client-esm/dice/terms/parenthetical.d.mts
index f5b871a1f..5745eb9a1 100644
--- a/src/foundry/client-esm/dice/terms/parenthetical.d.mts
+++ b/src/foundry/client-esm/dice/terms/parenthetical.d.mts
@@ -8,13 +8,13 @@ import type DiceTerm from "./dice.d.mts";
  * A type of RollTerm used to enclose a parenthetical expression to be recursively evaluated.
  */
 declare class ParentheticalTerm extends RollTerm {
-  constructor({ term, roll, options }: ParentheticalTerm.TermData);
+  constructor(termData?: InexactPartial<ParentheticalTerm.TermData>);
 
   /** The original provided string term used to construct the parenthetical */
-  term: ParentheticalTerm.TermData["term"];
+  term: string | undefined; // only one of term or roll is expected
 
   /** Alternatively, an already-evaluated Roll instance may be passed directly */
-  roll: ParentheticalTerm.TermData["roll"];
+  roll: Roll | undefined; // only one of term or roll is expected
 
   /**
    * Is this term intermediate, and should be evaluated first as part of the simplification process?
@@ -54,7 +54,7 @@ declare class ParentheticalTerm extends RollTerm {
   /** An array of evaluated DiceTerm instances that should be bubbled up to the parent Roll */
   get dice(): DiceTerm[];
 
-  override get total(): string | number | null | undefined;
+  override get total(): number | undefined;
 
   override get expression(): string;
 
@@ -69,8 +69,6 @@ declare class ParentheticalTerm extends RollTerm {
 
   protected _evaluateSync(roll: Roll, options?: InexactPartial<RollTerm.EvaluationOptions>): this;
 
-  /* -------------------------------------------- */
-
   /**
    * Construct a ParentheticalTerm from an Array of component terms which should be wrapped inside the parentheses.
    * @param terms - The array of terms to use as internal parts of the parenthetical
@@ -88,8 +86,6 @@ declare class ParentheticalTerm extends RollTerm {
    */
   static fromTerms(terms: RollTerm[], options?: InexactPartial<RollTerm.Options>): ParentheticalTerm;
 
-  /* -------------------------------------------- */
-
   /** Construct a Parenthetical from parser information. */
   static override fromParseNode(node: ParentheticalRollParseNode): ParentheticalTerm;
 }
diff --git a/src/foundry/client-esm/dice/terms/pool.d.mts b/src/foundry/client-esm/dice/terms/pool.d.mts
index 3f218d0ef..461395d04 100644
--- a/src/foundry/client-esm/dice/terms/pool.d.mts
+++ b/src/foundry/client-esm/dice/terms/pool.d.mts
@@ -22,27 +22,27 @@ import type Die from "./die.d.mts";
  * ```
  */
 declare class PoolTerm extends RollTerm {
-  constructor({ terms, modifiers, rolls, results, options }?: InexactPartial<PoolTerm.PoolTermConstructorData>);
+  constructor(terms?: PoolTerm.PoolTermConstructorData);
 
   /**
    * The original provided terms to the Dice Pool
    */
-  terms: PoolTerm.TermData["terms"];
+  terms: string[];
 
   /**
    * The string modifiers applied to resolve the pool
    */
-  modifiers: PoolTerm.TermData["modifiers"];
+  modifiers: (keyof PoolTerm.Modifiers)[];
 
   /**
    * Each component term of a dice pool is evaluated as a Roll instance
    */
-  rolls: PoolTerm.TermData["rolls"];
+  rolls: Roll[];
 
   /**
    * The array of dice pool results which have been rolled
    */
-  results: PoolTerm.TermData["results"];
+  results: DiceTerm.Result[];
 
   /**
    * Define the modifiers that can be used for this particular DiceTerm type.
@@ -91,19 +91,13 @@ declare class PoolTerm extends RollTerm {
 
   override get total(): undefined | number;
 
-  /* -------------------------------------------- */
-
   /**
    * Return an array of rolled values which are still active within the PoolTerm
    */
   get values(): number[];
 
-  /* -------------------------------------------- */
-
   override get isDeterministic(): boolean;
 
-  /* -------------------------------------------- */
-
   /**
    * Alter the DiceTerm by adding or multiplying the number of dice which are rolled
    * @param args - Arguments passed to each contained Roll#alter method.
@@ -117,16 +111,12 @@ declare class PoolTerm extends RollTerm {
 
   protected _evaluateSync(options?: InexactPartial<RollTerm.EvaluationOptions>): this;
 
-  /* -------------------------------------------- */
-
   /**
    * Use the same logic as for the DiceTerm to avoid duplication
    * @see DiceTerm#_evaluateModifiers
    */
   protected _evaluateModifiers(): void;
 
-  /* -------------------------------------------- */
-
   /**
    * Use the same logic as for the DiceTerm to avoid duplication
    * @see DiceTerm#_evaluateModifier
@@ -142,12 +132,8 @@ declare class PoolTerm extends RollTerm {
     data: Record<string, unknown>,
   ): FixedInstanceType<T>;
 
-  /* -------------------------------------------- */
-
   toJSON(): Record<string, unknown>;
 
-  /* -------------------------------------------- */
-
   /**
    * Given a string formula, create and return an evaluated PoolTerm object
    * @param formula - The string formula to parse
@@ -167,8 +153,6 @@ declare class PoolTerm extends RollTerm {
    */
   static fromRolls<T extends PoolTerm.AnyConstructor>(this: T, rolls?: Roll[]): FixedInstanceType<T>;
 
-  /* -------------------------------------------- */
-
   /** Construct a PoolTerm from parser information. */
   static fromParseNode(node: PoolRollParseNode): PoolTerm;
 
@@ -261,7 +245,7 @@ declare namespace PoolTerm {
     /**
      * @defaultValue `[]`
      */
-    modifiers?: string[] | undefined;
+    modifiers?: Array<keyof Modifiers> | undefined;
 
     /**
      * @defaultValue `[]`
diff --git a/src/foundry/client-esm/dice/terms/string.d.mts b/src/foundry/client-esm/dice/terms/string.d.mts
index e137900c4..918197020 100644
--- a/src/foundry/client-esm/dice/terms/string.d.mts
+++ b/src/foundry/client-esm/dice/terms/string.d.mts
@@ -5,9 +5,9 @@ import type RollTerm from "./term.d.mts";
  * A type of RollTerm used to represent strings which have not yet been matched.
  */
 declare class StringTerm extends RollTerm {
-  constructor({ term, options }: StringTerm.ConstructorData);
+  constructor({ term, options }: StringTerm.TermData);
 
-  term: StringTerm.ConstructorData["term"];
+  term: string;
 
   /**
    * @defaultValue `["term"]`
@@ -24,7 +24,7 @@ declare class StringTerm extends RollTerm {
 }
 
 declare namespace StringTerm {
-  interface ConstructorData {
+  interface TermData {
     term: string;
 
     options?: RollTerm.Options | undefined;
diff --git a/src/foundry/client-esm/dice/terms/term.d.mts b/src/foundry/client-esm/dice/terms/term.d.mts
index 7f37a8f8f..1db9dad19 100644
--- a/src/foundry/client-esm/dice/terms/term.d.mts
+++ b/src/foundry/client-esm/dice/terms/term.d.mts
@@ -4,7 +4,7 @@ import type { RollParseNode } from "../_types.mts";
 import type RollResolver from "../../applications/dice/roll-resolver.d.mts";
 
 declare abstract class RollTerm {
-  constructor({ options }?: InexactPartial<{ options: RollTerm.Options }>);
+  constructor(termData?: InexactPartial<{ options: RollTerm.Options }>);
 
   /** An object of additional options which describes and modifies the term. */
   options: RollTerm.Options;
@@ -132,7 +132,7 @@ declare namespace RollTerm {
   type AnyConstructor = typeof AnyRollTerm;
 
   interface Options {
-    flavor?: string;
+    flavor?: string | undefined | null;
   }
 
   interface EvaluationOptions {
diff --git a/src/foundry/client/config.d.mts b/src/foundry/client/config.d.mts
index 503970aaa..be88ec712 100644
--- a/src/foundry/client/config.d.mts
+++ b/src/foundry/client/config.d.mts
@@ -66,7 +66,7 @@ declare global {
         options?: AnyObject,
       ) => Promise<number | void>;
 
-      type RollFunction = (arg0: never, ...args: never[]) => MaybePromise<number>;
+      type RollFunction = (...args: Array<string | number>) => MaybePromise<number | `${number}`>;
 
       type DTermDiceStrings = "d4" | "d6" | "d8" | "d10" | "d12" | "d20" | "d100";
     }
diff --git a/src/foundry/common/primitives/number.d.mts b/src/foundry/common/primitives/number.d.mts
index 63a3d929d..35e0ba701 100644
--- a/src/foundry/common/primitives/number.d.mts
+++ b/src/foundry/common/primitives/number.d.mts
@@ -86,6 +86,6 @@ declare global {
      * @param n - The value to convert; typically a string, but may already be a number.
      * @returns The number that the string represents, or NaN if no number could be determined.
      */
-    fromString(str: string | number): Number;
+    fromString(str: string | number): number;
   }
 }
diff --git a/src/foundry/common/utils/bitmask.d.mts b/src/foundry/common/utils/bitmask.d.mts
index d67092ed1..e06e61e1f 100644
--- a/src/foundry/common/utils/bitmask.d.mts
+++ b/src/foundry/common/utils/bitmask.d.mts
@@ -1,4 +1,4 @@
-declare class InternalBitMask extends Number {
+export default class BitMask extends Number {
   /**
    * Create a new BitMask instance.
    * @param states    - An object containing valid states and their corresponding initial boolean values (default is null).
@@ -108,8 +108,3 @@ declare class InternalBitMask extends Number {
    */
   static generateShaderBitMaskConstants(states: string[]): string;
 }
-
-declare const BitMask: typeof InternalBitMask & (new (...args: any) => number);
-type BitMask = InternalBitMask & number;
-
-export default BitMask;
diff --git a/src/foundry/common/utils/color.d.mts b/src/foundry/common/utils/color.d.mts
index 519131df9..64053a0dd 100644
--- a/src/foundry/common/utils/color.d.mts
+++ b/src/foundry/common/utils/color.d.mts
@@ -1,15 +1,10 @@
 export default Color;
-
-// `Color#fromString` breaks inheritance
-declare class PatchedNumber extends Number {
-  static fromString(color: string): any;
-}
-
 /**
  * A representation of a color in hexadecimal format.
  * This class provides methods for transformations and manipulations of colors.
  */
-declare class InternalColor extends PatchedNumber {
+// @ts-expect-error 2417: Override of Color.fromString does not match Number.fromString
+declare class Color extends Number {
   /**
    * Is this a valid color?
    */
@@ -295,9 +290,6 @@ declare class InternalColor extends PatchedNumber {
   static fromLinearRGB(linear: Color.RGBColorVector): Color;
 }
 
-declare const Color: typeof InternalColor & (new (...args: any) => number);
-type Color = InternalColor & number;
-
 declare namespace Color {
   type RGBColorVector = [r: number, g: number, b: number];
   type RGBAColorVector = [r: number, g: number, b: number, a: number];


Test patch:
diff --git a/tests/foundry/client-esm/dice/dice/coin.test-d.ts b/tests/foundry/client-esm/dice/dice/coin.test-d.ts
index 9ccf31af6..6abe89707 100644
--- a/tests/foundry/client-esm/dice/dice/coin.test-d.ts
+++ b/tests/foundry/client-esm/dice/dice/coin.test-d.ts
@@ -1,19 +1,13 @@
-declare namespace Coin {
-  interface Modifiers {
-    testModifier1: (this: DiceTerm) => void;
-    testModifier2: (this: DiceTerm) => DiceTerm;
-    testModifier3: (this: DiceTerm, modifier: string) => undefined | DiceTerm;
-  }
-}
+import { expectTypeOf } from "vitest";
 
-Coin.MODIFIERS.testModifier1 = function (this: DiceTerm) {
-  return;
-};
+const coin = new foundry.dice.terms.Coin();
 
-Coin.MODIFIERS.testModifier2 = function (this: DiceTerm) {
-  return this;
-};
+expectTypeOf(coin.roll()).toEqualTypeOf<Promise<foundry.dice.terms.DiceTerm.Result>>();
 
-Coin.MODIFIERS.testModifier3 = function (this: DiceTerm, modifier: string) {
-  return modifier.length > 0 ? undefined : this;
-};
+declare const result: foundry.dice.terms.DiceTerm.Result;
+expectTypeOf(coin.getResultLabel(result)).toEqualTypeOf<string>();
+expectTypeOf(coin.getResultCSS(result)).toEqualTypeOf<(string | null)[]>();
+expectTypeOf(coin.call("")).toEqualTypeOf<void>();
+
+expectTypeOf(foundry.dice.terms.Coin.DENOMINATION).toEqualTypeOf<string>();
+expectTypeOf(foundry.dice.terms.Coin.MODIFIERS).toEqualTypeOf<foundry.dice.terms.Coin.Modifiers>();
diff --git a/tests/foundry/client-esm/dice/dice/dice.test-d.ts b/tests/foundry/client-esm/dice/dice/dice.test-d.ts
new file mode 100644
index 000000000..647847322
--- /dev/null
+++ b/tests/foundry/client-esm/dice/dice/dice.test-d.ts
@@ -0,0 +1,35 @@
+import { expectTypeOf } from "vitest";
+
+declare const diceTerm: foundry.dice.terms.DiceTerm;
+
+expectTypeOf(diceTerm.method).toEqualTypeOf<keyof typeof CONFIG.Dice.fulfillment.methods | null | undefined>();
+expectTypeOf(diceTerm.modifiers).toEqualTypeOf<string[]>();
+expectTypeOf(diceTerm.results).toEqualTypeOf<foundry.dice.terms.DiceTerm.Result[]>();
+expectTypeOf(diceTerm.number).toEqualTypeOf<number | undefined>();
+expectTypeOf(diceTerm.faces).toEqualTypeOf<number | undefined>();
+expectTypeOf(diceTerm.denomination).toEqualTypeOf<string>();
+expectTypeOf(diceTerm.dice).toEqualTypeOf<foundry.dice.terms.DiceTerm[]>();
+expectTypeOf(diceTerm.total).toEqualTypeOf<number | undefined>();
+expectTypeOf(diceTerm.values).toEqualTypeOf<number[]>();
+expectTypeOf(diceTerm.isDeterministic).toEqualTypeOf<boolean>();
+expectTypeOf(diceTerm.alter(3, 2)).toEqualTypeOf<foundry.dice.terms.DiceTerm>();
+expectTypeOf(diceTerm.roll()).toEqualTypeOf<Promise<foundry.dice.terms.DiceTerm.Result>>();
+expectTypeOf(diceTerm.mapRandomFace(4)).toEqualTypeOf<number>();
+expectTypeOf(diceTerm.randomFace()).toEqualTypeOf<number>();
+
+declare const result: foundry.dice.terms.DiceTerm.Result;
+expectTypeOf(diceTerm.getResultLabel(result)).toEqualTypeOf<string>();
+expectTypeOf(diceTerm.getResultCSS(result)).toEqualTypeOf<(string | null)[]>();
+expectTypeOf(diceTerm.getTooltipData()).toEqualTypeOf<foundry.dice.terms.DiceTerm.ToolTipData>();
+
+expectTypeOf(foundry.dice.terms.DiceTerm.DENOMINATION).toEqualTypeOf<string>();
+expectTypeOf(foundry.dice.terms.DiceTerm.MODIFIERS).toEqualTypeOf<foundry.dice.terms.DiceTerm.Modifiers>();
+expectTypeOf(foundry.dice.terms.DiceTerm.MODIFIERS_REGEXP_STRING).toEqualTypeOf<string>();
+expectTypeOf(foundry.dice.terms.DiceTerm.MODIFIER_REGEXP).toEqualTypeOf<RegExp>();
+expectTypeOf(foundry.dice.terms.DiceTerm.REGEXP).toEqualTypeOf<RegExp>();
+expectTypeOf(foundry.dice.terms.DiceTerm.SERIALIZE_ATTRIBUTES).toEqualTypeOf<string[]>();
+expectTypeOf(foundry.dice.terms.DiceTerm.compareResult(3, "", 4)).toEqualTypeOf<boolean>();
+expectTypeOf(foundry.dice.terms.DiceTerm.matchTerm("")).toEqualTypeOf<RegExpMatchArray | null>();
+
+declare const rema: RegExpMatchArray;
+expectTypeOf(foundry.dice.terms.DiceTerm.fromMatch(rema)).toEqualTypeOf<foundry.dice.terms.DiceTerm>();
diff --git a/tests/foundry/client-esm/dice/dice/die.test-d.ts b/tests/foundry/client-esm/dice/dice/die.test-d.ts
index 33d112cb0..ffe1bd363 100644
--- a/tests/foundry/client-esm/dice/dice/die.test-d.ts
+++ b/tests/foundry/client-esm/dice/dice/die.test-d.ts
@@ -1,19 +1,24 @@
-declare namespace Die {
-  interface Modifiers {
-    testModifier1: (this: DiceTerm) => void;
-    testModifier2: (this: DiceTerm) => DiceTerm;
-    testModifier3: (this: DiceTerm, modifier: string) => undefined | DiceTerm;
-  }
-}
+import { expectTypeOf } from "vitest";
 
-Die.MODIFIERS.testModifier1 = function (this: DiceTerm) {
-  return;
-};
+const die = new foundry.dice.terms.Die();
 
-Die.MODIFIERS.testModifier2 = function (this: DiceTerm) {
-  return this;
-};
+expectTypeOf(die.total).toEqualTypeOf<number | undefined>();
+expectTypeOf(die.denomination).toEqualTypeOf<string>();
+expectTypeOf(die.reroll("")).toEqualTypeOf<Promise<boolean | void>>();
+expectTypeOf(die.rerollRecursive("")).toEqualTypeOf<Promise<boolean | void>>();
+expectTypeOf(die.explode("")).toEqualTypeOf<Promise<boolean | void>>();
+expectTypeOf(die.explodeOnce("")).toEqualTypeOf<Promise<boolean | void>>();
+expectTypeOf(die.keep("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(die.drop("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(die.countSuccess("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(die.countFailures("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(die.countEven("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(die.countOdd("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(die.deductFailures("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(die.subtractFailures("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(die.marginSuccess("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(die.minimum("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(die.maximum("")).toEqualTypeOf<boolean | void>();
 
-Die.MODIFIERS.testModifier3 = function (this: DiceTerm, modifier: string) {
-  return modifier.length > 0 ? undefined : this;
-};
+expectTypeOf(foundry.dice.terms.Die.DENOMINATION).toEqualTypeOf<string>();
+expectTypeOf(foundry.dice.terms.Die.MODIFIERS).toEqualTypeOf<foundry.dice.terms.Die.Modifiers>();
diff --git a/tests/foundry/client-esm/dice/dice/fate.test-d.ts b/tests/foundry/client-esm/dice/dice/fate.test-d.ts
index 6500b50f5..8cb27daa0 100644
--- a/tests/foundry/client-esm/dice/dice/fate.test-d.ts
+++ b/tests/foundry/client-esm/dice/dice/fate.test-d.ts
@@ -1,19 +1,12 @@
-declare namespace FateDie {
-  interface Modifiers {
-    testModifier1: (this: DiceTerm) => void;
-    testModifier2: (this: DiceTerm) => DiceTerm;
-    testModifier3: (this: DiceTerm, modifier: string) => undefined | DiceTerm;
-  }
-}
+import { expectTypeOf } from "vitest";
 
-FateDie.MODIFIERS.testModifier1 = function (this: DiceTerm) {
-  return;
-};
+const fateDie = new foundry.dice.terms.FateDie();
 
-FateDie.MODIFIERS.testModifier2 = function (this: DiceTerm) {
-  return this;
-};
+expectTypeOf(fateDie.roll()).toEqualTypeOf<Promise<foundry.dice.terms.DiceTerm.Result>>();
+expectTypeOf(fateDie.mapRandomFace(5)).toEqualTypeOf<number>();
 
-FateDie.MODIFIERS.testModifier3 = function (this: DiceTerm, modifier: string) {
-  return modifier.length > 0 ? undefined : this;
-};
+declare const result: foundry.dice.terms.DiceTerm.Result;
+expectTypeOf(fateDie.getResultLabel(result)).toEqualTypeOf<string>();
+
+expectTypeOf(foundry.dice.terms.FateDie.DENOMINATION).toEqualTypeOf<string>();
+expectTypeOf(foundry.dice.terms.FateDie.MODIFIERS).toEqualTypeOf<foundry.dice.terms.FateDie.Modifiers>();
diff --git a/tests/foundry/client-esm/dice/dice/function.test-d.ts b/tests/foundry/client-esm/dice/dice/function.test-d.ts
new file mode 100644
index 000000000..97889f653
--- /dev/null
+++ b/tests/foundry/client-esm/dice/dice/function.test-d.ts
@@ -0,0 +1,23 @@
+import { expectTypeOf } from "vitest";
+import type { FunctionRollParseNode } from "../../../../../src/foundry/client-esm/dice/_types.d.mts";
+
+const functionTerm = new foundry.dice.terms.FunctionTerm({ fn: "max" });
+
+expectTypeOf(functionTerm.fn).toEqualTypeOf<string>();
+expectTypeOf(functionTerm.terms).toEqualTypeOf<string[]>();
+expectTypeOf(functionTerm.rolls).toEqualTypeOf<foundry.dice.Roll[]>();
+expectTypeOf(functionTerm.result).toEqualTypeOf<string | number | undefined>();
+expectTypeOf(functionTerm.isIntermediate).toEqualTypeOf<true>();
+expectTypeOf(functionTerm.dice).toEqualTypeOf<foundry.dice.terms.DiceTerm[]>();
+expectTypeOf(functionTerm.total).toEqualTypeOf<string | number>();
+expectTypeOf(functionTerm.expression).toEqualTypeOf<string>();
+expectTypeOf(functionTerm.function).toEqualTypeOf<CONFIG.Dice.RollFunction>();
+expectTypeOf(functionTerm.isDeterministic).toEqualTypeOf<boolean>();
+expectTypeOf(functionTerm.toJSON()).toEqualTypeOf<Record<string, unknown>>();
+
+expectTypeOf(functionTerm.expression).toEqualTypeOf<string>();
+
+expectTypeOf(foundry.dice.terms.FunctionTerm.SERIALIZE_ATTRIBUTES).toEqualTypeOf<["fn", "terms", "rolls", "result"]>();
+
+declare const node: FunctionRollParseNode;
+expectTypeOf(foundry.dice.terms.FunctionTerm.fromParseNode(node)).toEqualTypeOf<foundry.dice.terms.RollTerm>();
diff --git a/tests/foundry/client-esm/dice/dice/numeric.test-d.ts b/tests/foundry/client-esm/dice/dice/numeric.test-d.ts
new file mode 100644
index 000000000..a70f96ea7
--- /dev/null
+++ b/tests/foundry/client-esm/dice/dice/numeric.test-d.ts
@@ -0,0 +1,14 @@
+import { expectTypeOf } from "vitest";
+
+const numericTerm = new foundry.dice.terms.NumericTerm({ number: 6 });
+
+expectTypeOf(numericTerm.number).toEqualTypeOf<number>();
+expectTypeOf(numericTerm.expression).toEqualTypeOf<string>();
+expectTypeOf(numericTerm.total).toEqualTypeOf<number>();
+
+expectTypeOf(foundry.dice.terms.NumericTerm.REGEXP).toEqualTypeOf<RegExp>();
+expectTypeOf(foundry.dice.terms.NumericTerm.SERIALIZE_ATTRIBUTES).toEqualTypeOf<string[]>();
+expectTypeOf(foundry.dice.terms.NumericTerm.matchTerm("")).toEqualTypeOf<RegExpMatchArray | null>();
+
+declare const rema: RegExpMatchArray;
+expectTypeOf(foundry.dice.terms.NumericTerm.fromMatch(rema)).toEqualTypeOf<foundry.dice.terms.NumericTerm>();
diff --git a/tests/foundry/client-esm/dice/dice/operator.test-d.ts b/tests/foundry/client-esm/dice/dice/operator.test-d.ts
new file mode 100644
index 000000000..84fb3bf6d
--- /dev/null
+++ b/tests/foundry/client-esm/dice/dice/operator.test-d.ts
@@ -0,0 +1,19 @@
+import { expectTypeOf } from "vitest";
+
+const operatorTerm = new foundry.dice.terms.OperatorTerm({ operator: "+" });
+
+expectTypeOf(operatorTerm.operator).toEqualTypeOf<string>();
+expectTypeOf(operatorTerm.flavor).toEqualTypeOf<string>();
+expectTypeOf(operatorTerm.expression).toEqualTypeOf<string>();
+expectTypeOf(operatorTerm.total).toEqualTypeOf<string>();
+
+expectTypeOf(foundry.dice.terms.OperatorTerm.PRECEDENCE).toEqualTypeOf<{
+  "+": 10;
+  "-": 10;
+  "*": 20;
+  "/": 20;
+  "%": 20;
+}>();
+expectTypeOf(foundry.dice.terms.OperatorTerm.OPERATORS).toEqualTypeOf<string[]>();
+expectTypeOf(foundry.dice.terms.OperatorTerm.REGEXP).toEqualTypeOf<RegExp>();
+expectTypeOf(foundry.dice.terms.OperatorTerm.SERIALIZE_ATTRIBUTES).toEqualTypeOf<string[]>();
diff --git a/tests/foundry/client-esm/dice/dice/parenthetical.test-d.ts b/tests/foundry/client-esm/dice/dice/parenthetical.test-d.ts
new file mode 100644
index 000000000..8bdcd11b9
--- /dev/null
+++ b/tests/foundry/client-esm/dice/dice/parenthetical.test-d.ts
@@ -0,0 +1,24 @@
+import { expectTypeOf } from "vitest";
+import type { ParentheticalRollParseNode } from "../../../../../src/foundry/client-esm/dice/_types.d.mts";
+
+declare const roll: foundry.dice.Roll;
+const parentheticalTerm = new foundry.dice.terms.ParentheticalTerm({ term: "" });
+new foundry.dice.terms.ParentheticalTerm({ roll });
+
+expectTypeOf(parentheticalTerm.term).toEqualTypeOf<string | undefined>();
+expectTypeOf(parentheticalTerm.roll).toEqualTypeOf<foundry.dice.Roll | undefined>();
+expectTypeOf(parentheticalTerm.isIntermediate).toEqualTypeOf<boolean>();
+expectTypeOf(parentheticalTerm.dice).toEqualTypeOf<foundry.dice.terms.DiceTerm[]>();
+expectTypeOf(parentheticalTerm.total).toEqualTypeOf<number | undefined>();
+expectTypeOf(parentheticalTerm.expression).toEqualTypeOf<string>();
+expectTypeOf(parentheticalTerm.isDeterministic).toEqualTypeOf<boolean>();
+
+expectTypeOf(foundry.dice.terms.ParentheticalTerm.OPEN_REGEXP).toEqualTypeOf<RegExp>();
+expectTypeOf(foundry.dice.terms.ParentheticalTerm.CLOSE_REGEXP).toEqualTypeOf<RegExp>();
+expectTypeOf(foundry.dice.terms.ParentheticalTerm.SERIALIZE_ATTRIBUTES).toEqualTypeOf<string[]>();
+expectTypeOf(foundry.dice.terms.ParentheticalTerm.fromTerms([])).toEqualTypeOf<foundry.dice.terms.ParentheticalTerm>();
+
+declare const node: ParentheticalRollParseNode;
+expectTypeOf(
+  foundry.dice.terms.ParentheticalTerm.fromParseNode(node),
+).toEqualTypeOf<foundry.dice.terms.ParentheticalTerm>();
diff --git a/tests/foundry/client-esm/dice/dice/pool.test-d.ts b/tests/foundry/client-esm/dice/dice/pool.test-d.ts
new file mode 100644
index 000000000..b79189e0f
--- /dev/null
+++ b/tests/foundry/client-esm/dice/dice/pool.test-d.ts
@@ -0,0 +1,33 @@
+import { expectTypeOf } from "vitest";
+import type { ParentheticalRollParseNode } from "../../../../../src/foundry/client-esm/dice/_types.d.mts";
+
+const poolTerm = new foundry.dice.terms.PoolTerm();
+
+expectTypeOf(poolTerm.terms).toEqualTypeOf<string[]>();
+expectTypeOf(poolTerm.modifiers).toEqualTypeOf<(keyof foundry.dice.terms.PoolTerm.Modifiers)[]>();
+expectTypeOf(poolTerm.rolls).toEqualTypeOf<foundry.dice.Roll[]>();
+expectTypeOf(poolTerm.results).toEqualTypeOf<foundry.dice.terms.DiceTerm.Result[]>();
+expectTypeOf(poolTerm.dice).toEqualTypeOf<foundry.dice.terms.DiceTerm[]>();
+expectTypeOf(poolTerm.expression).toEqualTypeOf<string>();
+expectTypeOf(poolTerm.total).toEqualTypeOf<number | undefined>();
+expectTypeOf(poolTerm.values).toEqualTypeOf<number[]>();
+expectTypeOf(poolTerm.isDeterministic).toEqualTypeOf<boolean>();
+expectTypeOf(poolTerm.alter(3, 3)).toEqualTypeOf<foundry.dice.terms.PoolTerm>();
+expectTypeOf(poolTerm.toJSON()).toEqualTypeOf<Record<string, unknown>>();
+expectTypeOf(poolTerm.keep("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(poolTerm.drop("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(poolTerm.countSuccess("")).toEqualTypeOf<boolean | void>();
+expectTypeOf(poolTerm.countFailures("")).toEqualTypeOf<boolean | void>();
+
+expectTypeOf(foundry.dice.terms.PoolTerm.MODIFIERS).toEqualTypeOf<foundry.dice.terms.PoolTerm.Modifiers>();
+expectTypeOf(foundry.dice.terms.PoolTerm.OPEN_REGEXP).toEqualTypeOf<RegExp>();
+expectTypeOf(foundry.dice.terms.PoolTerm.CLOSE_REGEXP).toEqualTypeOf<RegExp>();
+expectTypeOf(foundry.dice.terms.PoolTerm.REGEXP).toEqualTypeOf<RegExp>();
+expectTypeOf(foundry.dice.terms.PoolTerm.SERIALIZE_ATTRIBUTES).toEqualTypeOf<string[]>();
+expectTypeOf(foundry.dice.terms.PoolTerm.fromExpression("")).toEqualTypeOf<foundry.dice.terms.PoolTerm | null>();
+expectTypeOf(foundry.dice.terms.PoolTerm.fromRolls([])).toEqualTypeOf<foundry.dice.terms.PoolTerm>();
+
+declare const node: ParentheticalRollParseNode;
+expectTypeOf(
+  foundry.dice.terms.ParentheticalTerm.fromParseNode(node),
+).toEqualTypeOf<foundry.dice.terms.ParentheticalTerm>();
diff --git a/tests/foundry/client-esm/dice/dice/string.test-d.ts b/tests/foundry/client-esm/dice/dice/string.test-d.ts
new file mode 100644
index 000000000..b256a45ac
--- /dev/null
+++ b/tests/foundry/client-esm/dice/dice/string.test-d.ts
@@ -0,0 +1,11 @@
+import { expectTypeOf } from "vitest";
+
+const stringTerm = new foundry.dice.terms.StringTerm({ term: "aaa" });
+
+expectTypeOf(stringTerm.term).toEqualTypeOf<string>();
+expectTypeOf(stringTerm.expression).toEqualTypeOf<string>();
+expectTypeOf(stringTerm.total).toEqualTypeOf<string>();
+expectTypeOf(stringTerm.isDeterministic).toEqualTypeOf<boolean>();
+expectTypeOf(stringTerm.evaluate()).toEqualTypeOf<never>();
+
+expectTypeOf(foundry.dice.terms.StringTerm.SERIALIZE_ATTRIBUTES).toEqualTypeOf<string[]>();
diff --git a/tests/foundry/client-esm/dice/dice/term.test-d.ts b/tests/foundry/client-esm/dice/dice/term.test-d.ts
new file mode 100644
index 000000000..8e90874f9
--- /dev/null
+++ b/tests/foundry/client-esm/dice/dice/term.test-d.ts
@@ -0,0 +1,28 @@
+import { expectTypeOf } from "vitest";
+import type { MaybePromise } from "fvtt-types/utils";
+import type { RollParseNode } from "../../../../../src/foundry/client-esm/dice/_types.d.mts";
+
+declare const rollTerm: foundry.dice.terms.RollTerm;
+
+expectTypeOf(rollTerm.options).toEqualTypeOf<foundry.dice.terms.RollTerm.Options>();
+expectTypeOf(rollTerm.isIntermediate).toEqualTypeOf<boolean>();
+expectTypeOf(rollTerm.expression).toEqualTypeOf<string>();
+expectTypeOf(rollTerm.formula).toEqualTypeOf<string>();
+expectTypeOf(rollTerm.total).toEqualTypeOf<number | string | null | undefined>();
+expectTypeOf(rollTerm.flavor).toEqualTypeOf<string>();
+expectTypeOf(rollTerm.isDeterministic).toEqualTypeOf<boolean>();
+expectTypeOf(rollTerm.resolver).toEqualTypeOf<foundry.applications.dice.RollResolver>();
+expectTypeOf(rollTerm.evaluate()).toEqualTypeOf<MaybePromise<foundry.dice.terms.RollTerm>>();
+expectTypeOf(rollTerm.toJSON()).toEqualTypeOf<Record<string, unknown>>();
+
+expectTypeOf(foundry.dice.terms.RollTerm.FLAVOR_REGEXP_STRING).toEqualTypeOf<string>();
+expectTypeOf(foundry.dice.terms.RollTerm.REGEXP).toEqualTypeOf<RegExp>();
+expectTypeOf(foundry.dice.terms.RollTerm.SERIALIZE_ATTRIBUTES).toEqualTypeOf<string[]>();
+
+declare const term: foundry.dice.terms.RollTerm;
+expectTypeOf(foundry.dice.terms.RollTerm.isDeterministic(term)).toEqualTypeOf<boolean>();
+expectTypeOf(foundry.dice.terms.RollTerm.fromData({})).toEqualTypeOf<foundry.dice.terms.RollTerm>();
+
+declare const node: RollParseNode;
+expectTypeOf(foundry.dice.terms.RollTerm.fromParseNode(node)).toEqualTypeOf<foundry.dice.terms.RollTerm>();
+expectTypeOf(foundry.dice.terms.RollTerm.fromJSON("")).toEqualTypeOf<foundry.dice.terms.RollTerm>();
diff --git a/tests/foundry/client-esm/dice/parser.test-d.ts b/tests/foundry/client-esm/dice/parser.test-d.ts
new file mode 100644
index 000000000..814a11a0b
--- /dev/null
+++ b/tests/foundry/client-esm/dice/parser.test-d.ts
@@ -0,0 +1,20 @@
+import { expectTypeOf } from "vitest";
+import type { RollParseArg, RollParseNode } from "../../../../src/foundry/client-esm/dice/_types.d.mts";
+
+const rollParser = new foundry.dice.RollParser("");
+
+expectTypeOf(rollParser.formula).toEqualTypeOf<string>();
+
+declare const node: RollParseNode;
+expectTypeOf(foundry.dice.RollParser.flattenTree(node)).toEqualTypeOf<RollParseNode[]>();
+
+declare const term: foundry.dice.terms.RollTerm;
+expectTypeOf(foundry.dice.RollParser.toAST(node)).toEqualTypeOf<RollParseNode>();
+expectTypeOf(foundry.dice.RollParser.toAST([term])).toEqualTypeOf<RollParseNode>();
+expectTypeOf(foundry.dice.RollParser.isOperatorTerm(node)).toEqualTypeOf<boolean>();
+expectTypeOf(foundry.dice.RollParser.isOperatorTerm(term)).toEqualTypeOf<boolean>();
+
+declare const arg: RollParseArg;
+expectTypeOf(foundry.dice.RollParser.formatList([arg])).toEqualTypeOf<string>();
+expectTypeOf(foundry.dice.RollParser.formatArg(arg)).toEqualTypeOf<string>();
+expectTypeOf(foundry.dice.RollParser.formatDebug("", arg)).toEqualTypeOf<string>();
diff --git a/tests/foundry/client-esm/dice/roll.test-d.ts b/tests/foundry/client-esm/dice/roll.test-d.ts
index bd1c0b26f..e61476cce 100644
--- a/tests/foundry/client-esm/dice/roll.test-d.ts
+++ b/tests/foundry/client-esm/dice/roll.test-d.ts
@@ -1,60 +1,125 @@
 import { expectTypeOf } from "vitest";
-import type { EmptyObject } from "fvtt-types/utils";
+import type { AnyObject, EmptyObject } from "fvtt-types/utils";
+import type { RollParseNode } from "../../../../src/foundry/client-esm/dice/_types.d.mts";
 
 class CustomRoll<D extends Record<string, unknown> = EmptyObject> extends Roll<D> {}
-
-CONFIG.Dice.rolls = [CustomRoll, Roll];
-
-const rollCls = CONFIG.Dice.rolls[0];
-
-expectTypeOf(rollCls.CHAT_TEMPLATE).toEqualTypeOf<string>();
+expectTypeOf(Roll).toEqualTypeOf<foundry.dice.Roll>();
 
 // Attack with advantage!
-const r = new Roll("2d20kh + @prof + @strMod", { prof: 2, strMod: 4 });
+type RollType = Roll<{ prof: number; strMod: number }>;
 
-// create the configured roll instance
-// TODO: Find way to ensure that first element of CONFIG.Dice.rolls array is used by `Roll.create`
-// expectTypeOf(Roll.create("1d20")).toEqualTypeOf<CustomRoll<EmptyObject>>();
-// expectTypeOf(Roll.create("1d20 + @prof", { prof: 2 })).toEqualTypeOf<CustomRoll<{ prof: number }>>();
-// expectTypeOf(Roll.fromTerms([])).toEqualTypeOf<Roll<EmptyObject>>();
-// expectTypeOf(CustomRoll.fromTerms([])).toEqualTypeOf<CustomRoll<EmptyObject>>();
+const roll = new Roll("2d20kh + @prof + @strMod", { prof: 2, strMod: 4 });
+expectTypeOf(roll.data).toEqualTypeOf<{ prof: number; strMod: number }>();
+expectTypeOf(roll.options).toEqualTypeOf<Roll.Options>();
 
 // The parsed terms of the roll formula
 // [Die, OperatorTerm, NumericTerm, OperatorTerm, NumericTerm]
-expectTypeOf(r.terms).toEqualTypeOf<foundry.dice.terms.RollTerm[]>();
+expectTypeOf(roll.terms).toEqualTypeOf<foundry.dice.terms.RollTerm[]>();
+
+expectTypeOf(roll.dice).toEqualTypeOf<foundry.dice.terms.DiceTerm[]>();
+expectTypeOf(roll.formula).toEqualTypeOf<string>();
+
+// The resulting equation after it was rolled
+expectTypeOf(roll.result).toEqualTypeOf<string>(); // 16 + 2 + 4
+
+// The total resulting from the roll
+expectTypeOf(roll.total).toEqualTypeOf<number | undefined>(); // 22
+
+expectTypeOf(roll.product).toEqualTypeOf<number | undefined>();
+expectTypeOf(roll.isDeterministic).toEqualTypeOf<boolean>();
+expectTypeOf(roll.alter(1, 2)).toEqualTypeOf<RollType>();
+expectTypeOf(roll.clone()).toEqualTypeOf<RollType>();
 
 // Execute the roll
 type TypeOfR = Roll<{ prof: number; strMod: number }>;
-expectTypeOf(r.evaluate()).toEqualTypeOf<Promise<foundry.dice.Roll.Evaluated<TypeOfR>>>();
-expectTypeOf(r.evaluate({ minimize: true, maximize: true })).toEqualTypeOf<
-  Promise<foundry.dice.Roll.Evaluated<TypeOfR>>
->();
-expectTypeOf((await r.evaluate()).total).toEqualTypeOf<number>();
+expectTypeOf(roll.evaluate()).toEqualTypeOf<Promise<Roll.Evaluated<TypeOfR>>>();
+expectTypeOf(roll.evaluate({ minimize: true, maximize: true })).toEqualTypeOf<Promise<Roll.Evaluated<TypeOfR>>>();
+expectTypeOf((await roll.evaluate()).total).toEqualTypeOf<number>();
 
-expectTypeOf(r.roll()).toEqualTypeOf<Promise<foundry.dice.Roll.Evaluated<TypeOfR>>>();
-expectTypeOf(r.roll()).toEqualTypeOf<Promise<foundry.dice.Roll.Evaluated<TypeOfR>>>();
-expectTypeOf(r.roll({ minimize: true, maximize: true })).toEqualTypeOf<Promise<foundry.dice.Roll.Evaluated<TypeOfR>>>();
-expectTypeOf((await r.roll()).total).toEqualTypeOf<number>();
+expectTypeOf(roll.evaluateSync()).toEqualTypeOf<Roll.Evaluated<TypeOfR>>();
 
-expectTypeOf(r.reroll()).toEqualTypeOf<Promise<foundry.dice.Roll.Evaluated<TypeOfR>>>();
-expectTypeOf(r.reroll({ minimize: true, maximize: true })).toEqualTypeOf<
-  Promise<foundry.dice.Roll.Evaluated<TypeOfR>>
->();
-expectTypeOf((await r.reroll()).total).toEqualTypeOf<number>();
+expectTypeOf(roll.roll()).toEqualTypeOf<Promise<Roll.Evaluated<TypeOfR>>>();
+expectTypeOf(roll.roll()).toEqualTypeOf<Promise<Roll.Evaluated<TypeOfR>>>();
+expectTypeOf(roll.roll({ minimize: true, maximize: true })).toEqualTypeOf<Promise<Roll.Evaluated<TypeOfR>>>();
+expectTypeOf((await roll.roll()).total).toEqualTypeOf<number>();
 
-// The resulting equation after it was rolled
-expectTypeOf(r.result).toEqualTypeOf<string>(); // 16 + 2 + 4
+declare const customRoll: CustomRoll<EmptyObject>;
+expectTypeOf(await customRoll.roll()).toEqualTypeOf<Roll.Evaluated<CustomRoll<EmptyObject>>>();
 
-// The total resulting from the roll
-expectTypeOf(r.total).toEqualTypeOf<number | undefined>(); // 22
+expectTypeOf(roll.reroll()).toEqualTypeOf<Promise<Roll.Evaluated<TypeOfR>>>();
+expectTypeOf(roll.reroll({ minimize: true, maximize: true })).toEqualTypeOf<Promise<Roll.Evaluated<TypeOfR>>>();
+expectTypeOf((await roll.reroll()).total).toEqualTypeOf<number>();
 
-declare const testBool: boolean;
+expectTypeOf(roll.resetFormula()).toEqualTypeOf<string>();
+expectTypeOf(roll.propagateFlavor("")).toEqualTypeOf<void>();
+expectTypeOf(roll.toString()).toEqualTypeOf<string>();
+expectTypeOf(roll.toAnchor()).toEqualTypeOf<HTMLAnchorElement>();
+expectTypeOf(roll.toJSON()).toEqualTypeOf<{
+  class: string;
+  options: Roll.Options;
+  dice: foundry.dice.terms.DiceTerm[];
+  formula: string;
+  terms: foundry.dice.terms.RollTerm[];
+  total: number | undefined;
+  evaluated: boolean;
+}>();
+expectTypeOf(roll.getTooltip()).toEqualTypeOf<Promise<string>>();
+expectTypeOf(roll.render()).toEqualTypeOf<Promise<string>>();
 
-expectTypeOf(r.toMessage()).toEqualTypeOf<Promise<ChatMessage | undefined>>();
-expectTypeOf(r.toMessage({}, { create: true })).toEqualTypeOf<Promise<ChatMessage | undefined>>();
-// eslint-disable-next-line @typescript-eslint/no-empty-object-type
-expectTypeOf(r.toMessage({}, { create: false })).toEqualTypeOf<Promise<foundry.dice.Roll.MessageData<{}>>>();
-expectTypeOf(r.toMessage({}, { create: testBool })).toEqualTypeOf<
-  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
-  Promise<ChatMessage | undefined | foundry.dice.Roll.MessageData<{}>>
+declare const testBool: boolean;
+expectTypeOf(roll.toMessage()).toEqualTypeOf<Promise<ChatMessage | undefined>>();
+expectTypeOf(roll.toMessage({}, { create: true })).toEqualTypeOf<Promise<ChatMessage | undefined>>();
+expectTypeOf(roll.toMessage({}, { create: false })).toEqualTypeOf<
+  Promise<foundry.data.fields.SchemaField.InnerPersistedType<ChatMessage.Schema>>
+>();
+expectTypeOf(roll.toMessage({}, { create: null })).toEqualTypeOf<
+  Promise<foundry.data.fields.SchemaField.InnerPersistedType<ChatMessage.Schema>>
 >();
+expectTypeOf(roll.toMessage({}, { create: testBool })).toEqualTypeOf<
+  Promise<ChatMessage | undefined | foundry.data.fields.SchemaField.InnerPersistedType<ChatMessage.Schema>>
+>();
+
+expectTypeOf(Roll.MATH_PROXY).toEqualTypeOf<Math>();
+expectTypeOf(Roll.CHAT_TEMPLATE).toEqualTypeOf<string>();
+expectTypeOf(Roll.TOOLTIP_TEMPLATE).toEqualTypeOf<string>();
+expectTypeOf(Roll.RESOLVERS).toEqualTypeOf<Map<Roll, foundry.applications.dice.RollResolver>>();
+
+// create the configured roll instance
+// TODO: Find way to ensure that first element of CONFIG.Dice.rolls array is used by `Roll.create`
+// expectTypeOf(Roll.create("1d20")).toEqualTypeOf<CustomRoll<EmptyObject>>();
+// expectTypeOf(Roll.create("1d20 + @prof", { prof: 2 })).toEqualTypeOf<CustomRoll<{ prof: number }>>();
+// expectTypeOf(Roll.fromTerms([])).toEqualTypeOf<CustomRoll<EmptyObject>>();
+// expectTypeOf(Roll.defaultImplementation).toEqualTypeOf<CustomRoll<EmptyObject>>();
+
+expectTypeOf(Roll.resolverImplementation).toEqualTypeOf<typeof foundry.applications.dice.RollResolver>();
+expectTypeOf(Roll.getFormula([])).toEqualTypeOf<string>();
+expectTypeOf(Roll.safeEval("")).toEqualTypeOf<number>();
+expectTypeOf(Roll.simplifyTerms([])).toEqualTypeOf<foundry.dice.terms.RollTerm[]>();
+expectTypeOf(Roll.simulate("")).toEqualTypeOf<Promise<number[]>>();
+expectTypeOf(Roll.registerResult("", "", 1)).toEqualTypeOf<boolean | void>();
+expectTypeOf(Roll.parse("", {})).toEqualTypeOf<foundry.dice.terms.RollTerm[]>();
+
+declare const rpn: RollParseNode;
+expectTypeOf(Roll.instantiateAST(rpn)).toEqualTypeOf<foundry.dice.terms.RollTerm[]>();
+expectTypeOf(Roll.replaceFormulaData("", {})).toEqualTypeOf<string>();
+expectTypeOf(Roll.validate("")).toEqualTypeOf<boolean>();
+expectTypeOf(Roll.identifyFulfillableTerms([])).toEqualTypeOf<foundry.dice.terms.DiceTerm[]>();
+expectTypeOf(Roll._classifyStringTerm("")).toEqualTypeOf<foundry.dice.terms.RollTerm>();
+
+declare const a: HTMLAnchorElement;
+expectTypeOf(Roll.expandInlineResult(a)).toEqualTypeOf<Promise<void>>();
+expectTypeOf(Roll.collapseInlineResult(a)).toEqualTypeOf<void>();
+
+declare const d: foundry.dice.Roll.Data;
+
+expectTypeOf(Roll.fromData(d)).toEqualTypeOf<Roll<AnyObject>>();
+expectTypeOf(Roll.fromJSON("")).toEqualTypeOf<Roll<AnyObject>>();
+expectTypeOf(Roll.fromTerms([])).toEqualTypeOf<Roll<AnyObject>>();
+
+expectTypeOf(CustomRoll.fromData(d)).toEqualTypeOf<CustomRoll<Record<string, unknown>>>();
+expectTypeOf(CustomRoll.fromJSON("")).toEqualTypeOf<CustomRoll<Record<string, unknown>>>();
+expectTypeOf(CustomRoll.fromTerms([])).toEqualTypeOf<CustomRoll<Record<string, unknown>>>();
+
+CONFIG.Dice.rolls = [CustomRoll, Roll];
+const rollCls = CONFIG.Dice.rolls[0];
+expectTypeOf(rollCls!.CHAT_TEMPLATE).toEqualTypeOf<string>();
diff --git a/tests/foundry/client-esm/dice/term.test-d.ts b/tests/foundry/client-esm/dice/term.test-d.ts
deleted file mode 100644
index 6dda582ff..000000000
--- a/tests/foundry/client-esm/dice/term.test-d.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { expectTypeOf } from "vitest";
-
-class CustomRollTerm extends RollTerm {
-  someProperty = 42;
-}
-
-const r = new CustomRollTerm();
-
-expectTypeOf(r.evaluate({ async: true })).toEqualTypeOf<Promise<CustomRollTerm>>();
-expectTypeOf(r.evaluate({ async: false })).toEqualTypeOf<CustomRollTerm>();
-expectTypeOf(r.evaluate()).toEqualTypeOf<CustomRollTerm>();
-expectTypeOf(r.evaluate({ minimize: true, maximize: true })).toEqualTypeOf<CustomRollTerm>();
-expectTypeOf(r.evaluate({ minimize: true, maximize: true, async: false as boolean })).toEqualTypeOf<
-  CustomRollTerm | Promise<CustomRollTerm>
->();
-expectTypeOf(r.evaluate({ minimize: true, maximize: true, async: false as boolean | undefined })).toEqualTypeOf<
-  CustomRollTerm | Promise<CustomRollTerm>
->();
-expectTypeOf(
-  r.evaluate({ minimize: true, maximize: true, async: false as false | undefined }),
-).toEqualTypeOf<CustomRollTerm>();
-expectTypeOf(r.evaluate({ minimize: true, maximize: true, async: false as true | undefined })).toEqualTypeOf<
-  CustomRollTerm | Promise<CustomRollTerm>
->();
diff --git a/tests/foundry/client-esm/dice/twister.test-d.ts b/tests/foundry/client-esm/dice/twister.test-d.ts
new file mode 100644
index 000000000..6fe739e75
--- /dev/null
+++ b/tests/foundry/client-esm/dice/twister.test-d.ts
@@ -0,0 +1,17 @@
+import { expectTypeOf } from "vitest";
+
+const twister = new foundry.dice.MersenneTwister(4);
+
+expectTypeOf(twister.seed(4)).toEqualTypeOf<number>();
+expectTypeOf(twister.seedArray([])).toEqualTypeOf<void>();
+expectTypeOf(twister.int()).toEqualTypeOf<number>();
+expectTypeOf(twister.int31()).toEqualTypeOf<number>();
+expectTypeOf(twister.real()).toEqualTypeOf<number>();
+expectTypeOf(twister.realx()).toEqualTypeOf<number>();
+expectTypeOf(twister.rnd()).toEqualTypeOf<number>();
+expectTypeOf(twister.random()).toEqualTypeOf<number>();
+expectTypeOf(twister.rndHiRes()).toEqualTypeOf<number>();
+expectTypeOf(twister.normal(1, 2)).toEqualTypeOf<number>();
+
+expectTypeOf(foundry.dice.MersenneTwister.random()).toEqualTypeOf<number>();
+expectTypeOf(foundry.dice.MersenneTwister.normal(1, 2)).toEqualTypeOf<number>();
diff --git a/tests/foundry/client/head.test-d.ts b/tests/foundry/client/head.test-d.ts
index d71d551b0..c393abfae 100644
--- a/tests/foundry/client/head.test-d.ts
+++ b/tests/foundry/client/head.test-d.ts
@@ -7,4 +7,4 @@ expectTypeOf(ui.menu).toEqualTypeOf<MainMenu | undefined>();
 
 const myColor = Color.from("foobar");
 
-expectTypeOf(myColor).toEqualTypeOf<number | Color>();
+expectTypeOf(myColor).toEqualTypeOf<Color>();
diff --git a/tests/foundry/common/utils/bitmask.mjs.test-d.ts b/tests/foundry/common/utils/bitmask.mjs.test-d.ts
index 32e8d26d5..53a317619 100644
--- a/tests/foundry/common/utils/bitmask.mjs.test-d.ts
+++ b/tests/foundry/common/utils/bitmask.mjs.test-d.ts
@@ -1,7 +1,6 @@
 import { expectTypeOf } from "vitest";
 
 const b = new foundry.utils.BitMask();
-const _number: number = b;
 
 expectTypeOf(b.hasState("a")).toEqualTypeOf<boolean>();
 expectTypeOf(b.addState("a")).toEqualTypeOf<void>();
diff --git a/tests/foundry/common/utils/color.mjs.test-d.mts b/tests/foundry/common/utils/color.mjs.test-d.mts
deleted file mode 100644
index 97837d0ab..000000000
--- a/tests/foundry/common/utils/color.mjs.test-d.mts
+++ /dev/null
@@ -1,2 +0,0 @@
-const _color1: number = new Color(0xffffff);
-const _color2: number = Color.from(0xffff00);