Skip to content

No Chained Type Assertions

Error
small-rules/no-chained-type-assertions

Disallow chained TypeScript as and angle-bracket assertions, including parenthesized chains.

Rationale

Ported from dmmulroy/anti-slop’s no-chained-type-assertions — I wanted the same guard against casts that fabricate evidence. Credit for the rule idea is his; the port here just matches my checker and my one carve-out.

  • Fabricated evidence: the second as (or angle-bracket) doesn’t narrow anything — it just discards whatever the first one claimed. value as string as number proves neither.

  • Boundary parsing over brute-forcing: when you see as unknown as T or as any as T the input is probably untrusted. I’d rather you validate it at the boundary with a guard or schema and keep the precise type from there. Almost never worth papering over.

  • Parenthesized chains count: (value as string) as number is the same trick with parens. The rule unwraps them, so you can’t hide it.

Where I differ is I allow as const as const. It’s idempotent — it doesn’t widen or narrow, so there’s nothing to discard. I also let you name specific identifier targets for a single as unknown as T bridge via allowedTargets. That’s for nominal twins like Roblox vector / Vector3, not a free pass: as unknown as string still flags. Everything else with two non-const assertions is a problem.

Diagnostic Messages

chained
This assertion chain discards type evidence. Keep the original precise type, or parse untrusted input at its boundary before narrowing it.

Configuration

This rule accepts one options object after the severity.

allowedTargetsOptional

Identifier names allowed as the final target of a single `as unknown/any/never as T` bridge, e.g. `vector` or `Vector3`.

{
"jsPlugins": [
"@pobammer-ts/small-rules"
],
"rules": {
"small-rules/no-chained-type-assertions": [
"error",
{
"allowedTargets": []
}
]
}
}

Examples

chained as assertions
const x = value as string as number;
satisfies instead of a second assertion
const x = value satisfies string;