Structural weight
Unions, intersections, and optional properties add more weight than simple primitives.
Require Ianitor.Check<T> validators when a TypeScript type gets too complex to trust at runtime.
TypeScript types evaporate at runtime. If your code reads data from a DataStore, RemoteEvent, or any other IO boundary, TypeScript has no way to prove the data matches your type. This rule scores the structural complexity of your types and reports an error when the score crosses a threshold, nudging you to add an Ianitor runtime validator.
baseThreshold (default 10), the rule reports an error.type MyType = Ianitor.Static<typeof myValidator> so the runtime check and the
TypeScript type stay in sync.This type is too deeply nested to trust without a runtime check.
type UserPayload = { data: { preferences: { theme: string; blurEnabled: boolean; }; lastLogin: number; };};Define the validator once and extract the TypeScript type from it.
const userValidator = Ianitor.interface({ data: Ianitor.interface({ preferences: Ianitor.interface({ ... }), lastLogin: Ianitor.number(), }),});
type UserPayload = Ianitor.Static<typeof userValidator>;The rule accepts a single options object with these fields:
| Option | Type | Default | What it controls |
|---|---|---|---|
baseThreshold | number | 10 | Minimum complexity score before the rule reports. |
warnThreshold | number | 15 | Score at which the rule starts warning. |
errorThreshold | number | 25 | Score at which the violation becomes an error. |
interfacePenalty | number | 20 | Base score added to all interface declarations. |
performanceMode | boolean | true | Cap scores at 2x errorThreshold to avoid expensive walks. |
Structural weight
Unions, intersections, and optional properties add more weight than simple primitives.
Nesting depth
Each level of nesting multiplies the score via log2(depth + 1).
Property count
Large objects with many fields are penalized to encourage smaller sub-interfaces.
Caching
The rule caches complexity scores per node so re-checking stays cheap.