type-safety

star 13

Apply type safety patterns including nullable types, validation, static analysis, and strong typing. Use when adding type annotations, implementing nullable reference types, validating inputs with value objects, configuring static analysis tools, or designing type-safe APIs.

jnPiyush By jnPiyush schedule Updated 3/4/2026

name: "type-safety" description: 'Apply type safety patterns including nullable types, validation, static analysis, and strong typing. Use when adding type annotations, implementing nullable reference types, validating inputs with value objects, configuring static analysis tools, or designing type-safe APIs.' metadata: author: "AgentX" version: "1.0.0" created: "2025-01-15" updated: "2025-01-15"

Type Safety

Purpose: Use type systems to catch errors at compile/analysis time rather than runtime. Goal: Prevent null errors, type mismatches, and invalid states. Note: For implementation, see C# Development or Python Development.


When to Use This Skill

  • Adding type annotations to existing code
  • Implementing nullable reference types
  • Building type-safe APIs with value objects
  • Configuring static analysis tools
  • Designing strongly-typed data transfer objects

Prerequisites

  • Language with type system support

Decision Tree

Type safety concern?
+-- Adding types to existing code?
|   +-- Greenfield? -> Enable strict mode from day one
|   +-- Legacy codebase? -> Enable strict incrementally (file-by-file)
|   +-- Third-party input? -> Validate at boundary, trust internally
+-- Choosing a type strategy?
|   +-- Primitive obsession? -> Introduce value objects (Email, Money, UserId)
|   +-- Magic strings/numbers? -> Replace with enums or constants
|   +-- Nullable confusion? -> Enable nullable reference types, annotate everything
+-- Handling unknown data?
|   +-- API response -> Parse and validate into typed model (Pydantic, Zod, etc.)
|   +-- User input -> Validate at boundary, reject invalid shapes early
|   +-- Config values -> Bind to typed config class at startup
+-- Compiler/analyzer errors?
    +-- Too many `any`/`object`? -> Replace with generics or specific types
    +-- Null warnings? -> Add explicit null checks or use non-null assertions with care
    +-- False positive? -> Suppress with inline comment explaining why

Why Type Safety Matters

Runtime Error (Bad):
 function getUser(id):
 return database.find(id) # What type? Nullable?
 
 user = getUser(123)
 print(user.email) # NullReferenceException at runtime

Type-Safe (Good):
 function getUser(id: int) -> User | null:
 return database.find(id)
 
 user = getUser(123)
 if user != null:
 print(user.email) # [PASS] Compiler ensures null check

Nullable Types

Concept

Explicitly declare whether a value can be null/None.

Type Declarations:
 
 User - Never null (must have value)
 User? - Nullable (might be null)
 
Benefits:
 - Compiler/analyzer warns about potential null access
 - Forces explicit null handling
 - Self-documenting code

Null Handling Patterns

Pattern 1: Null Check
 user = findUser(id)
 if user != null:
 return user.email
 else:
 throw NotFoundException()

Pattern 2: Default Value
 user = findUser(id)
 return user?.email ?? "unknown@example.com"

Pattern 3: Early Return
 user = findUser(id)
 if user == null:
 return NotFound()
 
 # user is non-null from here
 return Ok(user)

Pattern 4: Required (Fail Fast)
 user = findUser(id) ?? throw NotFoundException(id)
 return user.email # Guaranteed non-null

Type Annotations

Function Signatures

Fully Typed Function:

 function calculateTotal(
 items: List<OrderItem>, # Input type
 discountPercent: decimal, # Primitive type
 taxRate: decimal? # Nullable parameter
 ) -> decimal: # Return type
 ...

Benefits:
 - Clear contract
 - IDE autocomplete
 - Compile-time validation
 - Documentation

Data Types

Primitive Types:
 int, float, decimal, string, bool, datetime

Collection Types:
 List<T> # Ordered, duplicates allowed
 Set<T> # Unique values
 Map<K, V> # Key-value pairs
 Array<T> # Fixed size

Custom Types:
 User # Class/struct
 OrderStatus # Enum
 Result<T, E> # Union/discriminated type

Core Rules

Practice Description
Annotate everything Types on all function parameters and returns
Enable strict mode Turn on all null safety and type checks
Avoid any/object Use specific types instead of escape hatches
Validate at boundaries Check external input, trust internal data
Use enums Replace magic strings/numbers with enums
Prefer immutability Use readonly/final where possible
Run analyzers in CI Fail builds on type errors
Document nullable intent Explicit ? for nullable, no ? for required

Anti-Patterns

  • Any Escape Hatch: Using any, object, or dynamic to bypass the type system -> Use generics, union types, or specific interfaces instead
  • Primitive Obsession: Passing raw strings for emails, IDs, or money amounts -> Wrap in value objects (EmailAddress, UserId, Money) with built-in validation
  • Nullable Everywhere: Making every field nullable "just in case" -> Only mark fields nullable when null is a valid domain state; prefer required by default
  • Stringly Typed Enums: Using plain strings where a finite set of values exists -> Define enums or literal union types for known value sets
  • Ignoring Analyzer Warnings: Suppressing all static analysis warnings to get a clean build -> Fix warnings or suppress individually with documented justification
  • Unsafe Casts: Using force-casts to silence type errors without validation -> Validate the shape first, then let the type system narrow naturally
  • Missing Return Types: Relying on type inference for public API return types -> Explicitly annotate return types on all public functions and methods

Type Safety Tools

Language Tools
C# Roslyn analyzers, nullable reference types, StyleCop
Python mypy, pyright, pydantic
TypeScript tsc strict mode, ESLint
Java SpotBugs, Error Prone, NullAway
Go go vet, staticcheck

See Also: Testing - C# Development - Python Development

Troubleshooting

Issue Solution
Too many any/Object types Replace with specific types or generics, enable strict mode incrementally
Generic type inference fails Add explicit type parameters at call site, check constraint compatibility
Static analysis too noisy Configure severity levels, suppress false positives with inline comments, fix incrementally

References

Install via CLI
npx skills add https://github.com/jnPiyush/AgentX --skill type-safety
Repository Details
star Stars 13
call_split Forks 3
navigation Branch main
article Path SKILL.md
More from Creator