typescript-safety
Secures TypeScript message boundaries using Zod validation and strict type safety rules.
Install
mkdir -p .claude/skills/typescript-safety && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/18445" && unzip -o skill.zip -d .claude/skills/typescript-safety && rm skill.zipInstalls to .claude/skills/typescript-safety
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Use when writing TypeScript at message boundaries, runtime inputs, shared contracts, or any code that crosses the content-script/SW/backend trust boundary — to enforce Zod validation, discriminated unions, no-any rules, and sender verification.Key capabilities
- →Validate messages with Zod schemas at SW port boundaries
- →Verify message sender before processing port messages
- →Enforce no `any` in shared contracts
- →Use `unknown` and narrowing for I/O boundaries
- →Implement discriminated unions for message verb dispatch
- →Enable strict mode in `tsconfig.json`
How it works
The skill enforces type safety by validating all inbound messages with Zod schemas, verifying senders, and applying strict TypeScript rules at trust boundaries.
Inputs & outputs
When to use typescript-safety
- →Validate runtime inputs from external sources
- →Secure message handlers in background scripts
- →Define type-safe contract interfaces
- →Prevent runtime crashes from malformed JSON
About this skill
TypeScript Safety
When to Use
Use this skill when:
- writing or reviewing message handlers at the SW port boundary
- defining or consuming types in
shared/contracts/ - parsing runtime inputs from external sources (backend SSE, storage, page DOM)
- any code uses
as,any, or untypedJSON.parse - TypeScript errors are flagged by the post-edit verification hook
This skill is triggered by the index.ts error hotspot pattern. The 14+ recurring errors in pending-improvements.md trace largely to unguarded message shapes and implicit any in I/O paths.
When Not to Use
Do not use this skill for:
- pure CSS or DOM geometry work with no runtime parsing
- documentation-only changes
Files and Surfaces
Primary files:
extension/src/content/index.tsextension/src/background/index.tsshared/contracts/domain.tsshared/contracts/sse.tsbackend/src/lib/schemas.ts
Core Rules
Rule 1: Zod Schemas at Every Message Boundary
All messages received at the SW port handler must be validated with a Zod schema before dispatch. Use safeParse — never parse — inside message handlers.
import { z } from 'zod';
const InboundMessageSchema = z.discriminatedUnion('verb', [
z.object({ verb: z.literal('SEGMENT'), payload: SegmentPayloadSchema }),
z.object({ verb: z.literal('ENHANCE'), payload: EnhancePayloadSchema }),
z.object({ verb: z.literal('BIND'), payload: BindPayloadSchema }),
z.object({ verb: z.literal('CANCEL'), payload: z.object({ tabId: z.number() }) }),
]);
port.onMessage.addListener((raw) => {
const result = InboundMessageSchema.safeParse(raw);
if (!result.success) {
console.warn('[SW] invalid message shape', result.error.flatten());
return; // reject without throwing
}
dispatch(result.data);
});
Rule 2: Sender Verification Before Processing
Verify the message sender before acting on any port message. Reject messages from unknown origins silently.
chrome.runtime.onConnect.addListener((port) => {
// Only accept connections from this extension's own content scripts
if (port.sender?.id !== chrome.runtime.id) {
port.disconnect();
return;
}
// proceed with message handling
});
Rule 3: No any in Shared Contracts
All types in shared/contracts/ must be fully typed. Ban any with a lint rule or a code comment policy.
// WRONG
export type Section = { goal_type: any; text: any };
// CORRECT
export type GoalType = 'action' | 'tech_stack' | 'constraint' | 'output_format' | 'context' | 'edge_case';
export type Section = { goal_type: GoalType; text: string };
Rule 4: Use unknown + Narrowing at All I/O Boundaries
When receiving data from JSON.parse, chrome.storage, or SSE events, type the input as unknown and narrow explicitly.
// CORRECT
chrome.storage.sync.get('mode', (data: unknown) => {
const result = ModeSchema.safeParse((data as Record<string, unknown>)?.mode);
const mode = result.success ? result.data : 'balanced';
});
// WRONG
chrome.storage.sync.get('mode', (data: any) => {
const mode = data.mode; // no validation
});
Rule 5: Discriminated Unions for Message Verb Dispatch
Use TypeScript discriminated unions so the compiler enforces exhaustive handling of all verb types.
type InboundMessage =
| { verb: 'SEGMENT'; payload: SegmentPayload }
| { verb: 'ENHANCE'; payload: EnhancePayload }
| { verb: 'BIND'; payload: BindPayload }
| { verb: 'CANCEL'; payload: { tabId: number } };
function dispatch(msg: InboundMessage) {
switch (msg.verb) {
case 'SEGMENT': return handleSegment(msg.payload);
case 'ENHANCE': return handleEnhance(msg.payload);
case 'BIND': return handleBind(msg.payload);
case 'CANCEL': return handleCancel(msg.payload);
// TypeScript will error here if a new verb is added without a handler
}
}
Rule 6: tsconfig.json Must Have "strict": true
The extension and backend packages must both enable strict mode. This catches implicit any, null dereferences, and unchecked optional access.
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true
}
}
Rule 7: Type SSE Events Explicitly
SSE MessageEvent.data is typed as string — parse it explicitly before use.
evtSource.addEventListener('message', (e: MessageEvent<string>) => {
if (e.data === '[DONE]') return finalize();
const result = TokenChunkSchema.safeParse(JSON.parse(e.data));
if (!result.success) return; // malformed token — skip silently
appendGhostText(result.data.token);
});
Rule 8: Never Cast with as to Skip Validation
Use as only for DOM type widening (as HTMLTextAreaElement) or when TypeScript inference is provably wrong. Never use as to suppress a type error at an I/O boundary.
// ACCEPTABLE — DOM narrowing
const ta = document.getElementById('foo') as HTMLTextAreaElement;
// WRONG — bypasses runtime safety
const msg = rawMessage as BindPayload; // no validation
Deliverables
- Zod schemas defined for all inbound message shapes
safeParseused in all message handlers — no thrown validation errors- Sender ID verified before processing any port connection
- No
anyinshared/contracts/files - Discriminated union on
verbfield for the message router "strict": trueconfirmed intsconfig.jsonfor extension and backend packages- All SSE event data parsed through Zod before use
When not to use it
- →For pure CSS or DOM geometry work with no runtime parsing
Limitations
- →The skill does not apply to pure CSS or DOM geometry work
- →The skill does not apply to documentation-only changes
- →The skill bans `any` in shared contracts
How it compares
This approach systematically applies type safety and validation at critical system boundaries, preventing common runtime errors that manual coding might miss.
Compared to similar skills
typescript-safety side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| typescript-safety (this skill) | 0 | 1mo | No flags | Advanced |
| tech-debt-analyzer | 5 | 8mo | Review | Intermediate |
| codex-code-review | 1 | 7mo | Review | Intermediate |
| tech-debt | 1 | 1mo | Review | Beginner |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
tech-debt-analyzer
ailabs-393
This skill should be used when analyzing technical debt in a codebase, documenting code quality issues, creating technical debt registers, or assessing code maintainability. Use this for identifying code smells, architectural issues, dependency problems, missing documentation, security vulnerabilities, and creating comprehensive technical debt documentation.
codex-code-review
tyrchen
Perform comprehensive code reviews using OpenAI Codex CLI. This skill should be used when users request code reviews, want to analyze diffs/PRs, need security audits, performance analysis, or want automated code quality feedback. Supports reviewing staged changes, specific files, entire directories, or git diffs.
tech-debt
vm0-ai
Technical debt management - scan codebase for bad smells and create tracking issues
security-scan
redpanda-data
Resolve npm dependency vulnerabilities detected by security scans.
dependency-vulnerability-triage
lichunboa
Turns npm audit/Snyk results into prioritized patch plans with severity assessment, safe upgrade paths, breaking change analysis, and rollback strategies. Use for "dependency security", "vulnerability patching", "npm audit", or "security updates".
chrome-devtools
mrgoonie
Browser automation, debugging, and performance analysis using Puppeteer CLI scripts. Use for automating browsers, taking screenshots, analyzing performance, monitoring network traffic, web scraping, form automation, and JavaScript debugging.