
ban-type-assertions
Ban as type assertions in a package via the @typescript-eslint/consistent-type-assertions lint rule, replacing them with compiler-verified type-safe alternatives. Use when enabling the assertion ban in a new package or fixing violations in an existing one.
- Installs
- 144
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/factory-ai/factory-plugins --skill ban-type-assertions- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads ban-type-assertions automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Ban Type Assertions
Enable @typescript-eslint/consistent-type-assertions with assertionStyle: 'never' in a package and replace all as X casts with patterns the compiler can verify.
Core Philosophy
Pick the strictly correct path, not the simpler one.
Every as assertion is a spot where the developer told the compiler "trust me." The goal is to make the compiler verify instead. If you replace as Foo with a type guard that is equally unverified, you have not improved anything -- you have just moved the assertion.
Quick Reference
- Rule:
@typescript-eslint/consistent-type-assertions - Config:
{ assertionStyle: 'never' } - Location:
packages/<name>/.eslintrc.js
Workflow
1. Enable the Rule
Add to the package's .eslintrc.js:
rules: {
'@typescript-eslint/consistent-type-assertions': ['error', { assertionStyle: 'never' }],
}
2. Enumerate Violations
cd packages/<name> && npm run lint 2>&1 | grep "consistent-type-assertions"
Group violations by file and pattern before fixing.
3. Research Before Fixing
Before writing any replacement code:
- Check for existing zod schemas -- grep for
Schemaalongside the type name in@factory/commonand across the repo. - Check if schemas exist but aren't exported -- if so, export them rather than creating new ones.
- Check for duplicate types/interfaces across packages -- consolidate into
@factory/commonif found. - Understand the data flow -- is this a parse boundary (external data), a narrowing site (union type), or a library type gap?
4. Fix Violations Using the Pattern Hierarchy
Tier 1: Zod Parsing (for external data boundaries)
Use for any data entering the system from JSON, disk, network, IPC, etc. This gives runtime validation, not just a type annotation.
// BAD
const data = JSON.parse(raw) as MyType;
// GOOD
const data = MySchema.parse(JSON.parse(raw));
Use safeParse when you need to handle errors gracefully (e.g., returning an error response with context like a request id):
// BAD: throws before you can extract the request id
const request = RequestSchema.parse(JSON.parse(raw));
// GOOD: safeParse lets you return a proper error
const parsed = RequestSchema.safeParse(JSON.parse(raw));
if (!parsed.success) {
return errorResponse(rawObj?.id ?? null, INVALID_PARAMS, parsed.error.message);
}
const request = parsed.data;
Tier 2: Control Flow Narrowing (for union types)
Use switch, in, instanceof, or discriminated unions:
// BAD
(error as NodeJS.ErrnoException).code
// GOOD
if (error instanceof Error && 'code' in error) {
const code = error.code;
}
// BAD
if (METHODS.has(method as Method)) { ... }
// GOOD: switch narrows exhaustively
switch (method) {
case 'foo':
case 'bar':
return handle(method); // narrowed
}
Tier 3: eslint-disable with Justification (last resort)
Only for genuinely unavoidable cases (library type gaps, generic parameters that can't be inferred). Always explain why:
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- ws library types require generic parameter
ws.on('message', handler);
Anti-Pattern: Type Guards That Are Disguised Assertions
// NOT an improvement -- checks shape but not content
function isDaemonRequest(x: unknown): x is DaemonRequest {
return typeof x === 'object' && x !== null && 'method' in x;
}
A zod schema validates values. A type guard like this is an unverified assertion with extra steps. Only use type guards when the narrowing logic is truly sufficient.
5. Use Strict Schemas, Not Permissive Ones
When a schema exists (e.g., SessionSettingsSchema), use it strictly rather than z.record(z.unknown()). This ensures forward compatibility -- if fields are removed in a migration, stale data gets cleaned on read.
// BAD: accepts anything
const settings = z.record(z.unknown()).parse(raw);
// GOOD: validates against the real shape
const settings = SessionSettingsSchema.parse(raw);
6. Promote Shared Schemas to @factory/common
If you find duplicate interfaces, types, or schemas across packages, consolidate them:
- Create the schema in
@factory/common/<domain>/<subdomain>/schema.ts - Put any enums in a sibling
enums.ts(required byfactory/enum-file-organization) - Export via a subpath (e.g.,
@factory/common/session/summary), not the barrelindex.ts - Delete all local duplicates
- Update all consumers to import from the common subpath
- Run
npm run knipat repo root to catch unused barrel re-exports
7. Fix Test Mocks to Match Schemas
Once you replace as X with .parse(), test mocks that relied on the assertion will fail validation. Fix the mocks -- do not disable the rule in tests.
Create helper functions to centralize valid test fixtures:
function mockSessionSummary(
overrides?: Partial<SessionSummaryEvent>,
): SessionSummaryEvent {
return {
type: 'session_start',
id: 'test-id',
title: 'Test Session',
owner: 'test-owner',
...overrides,
};
}
8. Parse at the Boundary, Inside Error Handling
Make sure parsing happens where failures produce proper error responses, not unhandled exceptions:
// BAD: parse outside try/catch -- if it throws, you lose context
const request = RequestSchema.parse(data);
try { handle(request); } catch { ... }
// GOOD: safeParse before try, handle error with context
const parsed = RequestSchema.safeParse(data);
if (!parsed.success) {
return errorResponse(rawData?.id ?? null, INVALID_PARAMS, parsed.error.message);
}
try { handle(parsed.data); } catch { ... }
Verification
Run for all affected packages (a change in @factory/common can break downstream lint):
# Lint (all affected packages)
cd packages/<name> && npm run lint
# Typecheck
npm run typecheck
# Tests
npm run test
# Unused exports (repo root)
npm run knip
Reminders
factory/enum-file-organizationrequires TypeScript enums to live in files namedenums.tsno-barrel-filesprevents re-exporting types from barrel files -- consumers must import from the subpath directly- When promoting types to common, add a
package.jsonexports entry for the new subpath if one doesn't exist - Test overrides for the rule in
.eslintrc.jsmay be needed if test files use assertion syntax in mock setup -- but prefer fixing mocks over disabling the rule
FAQ
What does the ban-type-assertions skill do?
Ban as type assertions in a package via the @typescript-eslint/consistent-type-assertions lint rule, replacing them with compiler-verified type-safe alternatives. Use when enabling the assertion ban in a new package or fixing violations in an existing one.
How do I install ban-type-assertions?
Run npx skills add https://github.com/factory-ai/factory-plugins --skill ban-type-assertions in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/ban-type-assertions/ (personal) or .claude/skills/ban-type-assertions/ (project).
Which AI agents can use ban-type-assertions?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is ban-type-assertions safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains ban-type-assertions?
It is published by factory-ai in factory-ai/factory-plugins, and it is an official skill from the maker of the technology it covers. It has 144 recorded installs.
More from factory-ai/factory-plugins
no-use-effect
factory-ai/factory-plugins
Enforce the no-useEffect rule when writing or reviewing React code. ACTIVATE when writing React components, refactoring existing useEffect calls, reviewing PRs with useEffect, or when an agent adds useEffect "just in case." Provides the five replacement patterns and the useMountEffect escape hatch.
human-writing
factory-ai/factory-plugins
Remove signs of AI-generated writing from text to make it sound more natural and human-written. Use when editing or reviewing any form of document including: markdown, technical docs, emails, blog posts, PRDs, or any dedicated writing content. Based on Wikipedia's comprehensive "Signs of AI writing" guide. Detects and fixes patterns including: inflated symbolism, promotional language, superficial -ing analyses, vague attributions, em dash overuse, rule of three, AI vocabulary words, negative parallelisms, and excessive conjunctive phrases.
simplify
factory-ai/factory-plugins
Review changed code for reuse, quality, and efficiency, then fix any issues found.
frontend-design
factory-ai/factory-plugins
Open the skill to read its SKILL.md instructions.
visual-design
factory-ai/factory-plugins
Image generation and presentations. Use when: - User asks for images: logos, icons, app assets, diagrams, flowcharts, architecture diagrams, patterns, textures, photo edits, restorations - User needs a presentation or slide deck Covers nanobanana CLI for image generation and Slidev for presentations.
security-review
factory-ai/factory-plugins
Open the skill to read its SKILL.md instructions.
Popular code quality & workflow skills
grill-me
mattpocock/skills
A relentless interview to sharpen a plan or design.
improve-codebase-architecture
mattpocock/skills
Scan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.
handoff
mattpocock/skills
Compact the current conversation into a handoff document for another agent to pick up.
domain-modeling
mattpocock/skills
Build and sharpen a project's domain model. Use when discussing codebase terminology, writing or editing a GLOSSARY.md, or recording or editing an ADR.
codebase-design
mattpocock/skills
Shared vocabulary for designing deep modules. Use when the user wants to design or improve a module's interface, find deepening opportunities, decide where a seam goes, make code more testable or AI-navigable, or when another skill needs the deep-module vocabulary.
diagnosing-bugs
mattpocock/skills
Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.