can1357/oh-my-pi · error · OmpTypeError

cannot apply divisibility to ${this.ir.k}

Error message

cannot apply divisibility to ${this.ir.k}

What it means

`.divisibleBy(n)` is only defined for number types. `divisibleBy` checks `this.ir.k !== "number"` and throws an OmpTypeError naming the actual kind when called on any other type (string, object, boolean, etc.). Divisibility is a numeric-only constraint, so applying it elsewhere is a type-level misuse.

Source

Thrown at packages/omptype/src/type.ts:835

	atLeast(this: InternalType, bound: number): InternalType {
		return makeType(withNumericBound(this.ir, "min", bound), this[kSteps], metaOf(this));
	},

	atMost(this: InternalType, bound: number): InternalType {
		return makeType(withNumericBound(this.ir, "max", bound), this[kSteps], metaOf(this));
	},

	moreThan(this: InternalType, bound: number): InternalType {
		return makeType(withNumericBound(this.ir, "min", bound, true), this[kSteps], metaOf(this));
	},

	lessThan(this: InternalType, bound: number): InternalType {
		return makeType(withNumericBound(this.ir, "max", bound, true), this[kSteps], metaOf(this));
	},

	divisibleBy(this: InternalType, divisor: number): InternalType {
		if (this.ir.k !== "number") throw new OmpTypeError(`cannot apply divisibility to ${this.ir.k}`);
		if (!Number.isFinite(divisor) || divisor === 0) throw new OmpTypeError("divisor must be non-zero");
		return makeType({ ...this.ir, divisor }, this[kSteps], metaOf(this));
	},

	positive(this: InternalType): InternalType {
		return makeType(withNumericBound(this.ir, "min", 0, true), this[kSteps], metaOf(this));
	},

	negative(this: InternalType): InternalType {
		return makeType(withNumericBound(this.ir, "max", 0, true), this[kSteps], metaOf(this));
	},

	nonNegative(this: InternalType): InternalType {
		return makeType(withNumericBound(this.ir, "min", 0), this[kSteps], metaOf(this));
	},

	nonPositive(this: InternalType): InternalType {
		return makeType(withNumericBound(this.ir, "max", 0), this[kSteps], metaOf(this));

View on GitHub (pinned to 9690622007)

Solutions

  1. Ensure the receiver is a number type: `type('number').divisibleBy(2)`.
  2. If constraining integers, use `type('number.integer').divisibleBy(2)`.
  3. Check the message's `k` value to see which kind the receiver actually was and fix the base type expression.

Example fix

// before
const T = type('string').divisibleBy(2); // throws: cannot apply divisibility to string

// after
const T = type('number').divisibleBy(2);
Defensive patterns

Strategy: type-guard

Validate before calling

// ensure the receiver is numeric before chaining
const base = type('number'); // not string/object/union
const T = base.divisibleBy(2);

Type guard

function isNumberType(t) {
  try { return t.expression.startsWith('number'); } catch { return false; }
}

Try / catch

try {
  const T = maybeType.divisibleBy(2);
} catch (e) {
  if (e instanceof OmpTypeError && e.message.startsWith('cannot apply divisibility')) {
    // use a numeric base type instead
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `.divisibleBy(2)` on a non-number type, e.g. `type('string').divisibleBy(2)`, `type('boolean').divisibleBy(1)`, or chaining it onto an object/union type.

Common situations: Chaining constraint builders fluently and landing on the wrong base type; intending `type('number').divisibleBy(...)` but the expression resolves to a union or string due to a wrong type expression.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/903358bbae945352. Report an issue: GitHub.