type-patterns — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited type-patterns (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Apply advanced type-level patterns to model domains precisely and catch logic errors at compile time instead of runtime.
Use a shared literal property to let TypeScript narrow union members automatically.
interface Loading { status: "loading" }
interface Success<T> { status: "success"; data: T }
interface Failure { status: "error"; error: Error }
type AsyncState<T> = Loading | Success<T> | Failure;
function render(state: AsyncState<string>): string {
switch (state.status) {
case "loading":
return "Loading...";
case "success":
return state.data; // narrowed to Success<string>
case "error":
return state.error.message; // narrowed to Failure
}
}Guarantee every union variant is handled. If a new variant is added, the compiler flags every switch that misses it.
function assertNever(value: never): never {
throw new Error(`Unhandled value: ${JSON.stringify(value)}`);
}
type Shape =
| { kind: "circle"; radius: number }
| { kind: "rect"; width: number; height: number }
| { kind: "triangle"; base: number; height: number };
function area(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "rect":
return shape.width * shape.height;
case "triangle":
return (shape.base * shape.height) / 2;
default:
return assertNever(shape); // compile error if a case is missing
}
}Prevent mixing structurally identical types by attaching a phantom brand.
type Brand<T, B extends string> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
type OrderId = Brand<string, "OrderId">;
function createUserId(id: string): UserId {
return id as UserId;
}
function createOrderId(id: string): OrderId {
return id as OrderId;
}
function getUser(id: UserId): void { /* ... */ }
const userId = createUserId("u-123");
const orderId = createOrderId("o-456");
getUser(userId); // OK
// getUser(orderId); // Compile error -- OrderId is not UserIdBuild type-safe string patterns that the compiler validates.
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type ApiVersion = "v1" | "v2";
type Resource = "users" | "orders" | "products";
type ApiRoute = `/${ApiVersion}/${Resource}`;
// "/v1/users" | "/v1/orders" | "/v1/products" | "/v2/users" | ...
type EventName<T extends string> = `on${Capitalize<T>}`;
type ClickEvent = EventName<"click">; // "onClick"
// Infer parts from template literals
type ExtractResource<T> = T extends `/${string}/${infer R}` ? R : never;
type Route = ExtractResource<"/v1/users">; // "users"Use as const to preserve literal types and create fully immutable structures.
// Without as const: type is { method: string; url: string }
// With as const: type preserves exact literals
const config = {
method: "GET",
url: "/api/users",
headers: ["Content-Type", "Authorization"],
} as const;
// config.method is "GET", not string
// config.headers is readonly ["Content-Type", "Authorization"]
// Derive union types from const objects
const STATUS_CODES = {
OK: 200,
NOT_FOUND: 404,
SERVER_ERROR: 500,
} as const;
type StatusCode = (typeof STATUS_CODES)[keyof typeof STATUS_CODES];
// 200 | 404 | 500
// Derive from const arrays
const ROLES = ["admin", "editor", "viewer"] as const;
type Role = (typeof ROLES)[number]; // "admin" | "editor" | "viewer"Create reusable runtime checks that inform the compiler.
interface ApiError {
code: number;
message: string;
}
function isApiError(value: unknown): value is ApiError {
return (
typeof value === "object" &&
value !== null &&
"code" in value &&
"message" in value &&
typeof (value as ApiError).code === "number" &&
typeof (value as ApiError).message === "string"
);
}
async function fetchData(url: string): Promise<string> {
const response = await fetch(url);
const body: unknown = await response.json();
if (isApiError(body)) {
throw new Error(`API error ${body.code}: ${body.message}`);
}
return body as string;
}enums when variants carry different data. Enums alone cannot narrow.
as to brand constructors only. Every otherusage should rely on narrowing.
silently fall through with undefined behavior.
as const makes the value deeply readonly.Do not assign it to a mutable variable and expect mutation to work.
| Pattern | Use Case |
|---|---|
| Discriminated unions | Multi-state data, state machines |
| Exhaustive check (never) | Guarantee all cases handled |
| Branded types | Prevent ID/value mixing |
| Template literal types | Type-safe string patterns |
| const assertions | Immutable configs, derive unions |
| Type guards | Runtime validation with type narrowing |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.