typescript by prowler-cloud/prowler
npx skills add https://github.com/prowler-cloud/prowler --skill typescript// ✅ 始终:先创建常量对象,再提取类型
const STATUS = {
ACTIVE: "active",
INACTIVE: "inactive",
PENDING: "pending",
} as const;
type Status = (typeof STATUS)[keyof typeof STATUS];
// ❌ 禁止:直接使用联合类型
type Status = "active" | "inactive" | "pending";
原因: 单一数据源、运行时值、自动补全、更易重构。
// ✅ 始终:单层深度,嵌套对象 → 专用接口
interface UserAddress {
street: string;
city: string;
}
interface User {
id: string;
name: string;
address: UserAddress; // 引用,而非内联
}
interface Admin extends User {
permissions: string[];
}
// ❌ 禁止:内联嵌套对象
interface User {
address: { street: string; city: string }; // 禁止!
}
any// ✅ 对于真正未知的类型使用 unknown
function parse(input: unknown): User {
if (isUser(input)) return input;
throw new Error("Invalid input");
}
// ✅ 对于灵活类型使用泛型
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
// ❌ 禁止
function parse(input: any): any { }
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
Pick<User, "id" | "name"> // 选择字段
Omit<User, "id"> // 排除字段
Partial<User> // 全部可选
Required<User> // 全部必需
Readonly<User> // 全部只读
Record<string, User> // 对象类型
Extract<Union, "a" | "b"> // 从联合类型中提取
Exclude<Union, "a"> // 从联合类型中排除
NonNullable<T | null> // 移除 null/undefined
ReturnType<typeof fn> // 函数返回类型
Parameters<typeof fn> // 函数参数元组
function isUser(value: unknown): value is User {
return (
typeof value === "object" &&
value !== null &&
"id" in value &&
"name" in value
);
}
不要将语义上耦合的属性建模为独立可选属性——这会允许无效的半状态,这些状态能通过编译但会在运行时出错。使用带有 never 的可辨识联合类型,使无效组合变得不可能。
// ❌ 之前:独立可选属性——允许半状态
interface PaginationProps {
onPageChange?: (page: number) => void;
pageSize?: number;
currentPage?: number;
}
// ✅ 之后:可辨识联合类型——要么全有,要么全无
type ControlledPagination = {
controlled: true;
currentPage: number;
pageSize: number;
onPageChange: (page: number) => void;
};
type UncontrolledPagination = {
controlled: false;
currentPage?: never;
pageSize?: never;
onPageChange?: never;
};
type PaginationProps = ControlledPagination | UncontrolledPagination;
关键规则: 如果两个或多个属性只有在一起时才有意义,它们应属于同一个可辨识联合分支。将它们作为独立可选属性混合使用,会将正确性的责任从类型系统转移到运行时守卫。
import type { User } from "./types";
import { createUser, type Config } from "./utils";
每周安装量
110
代码仓库
GitHub 星标
13.4K
首次出现
2026年1月21日
安全审计
安装于
opencode97
gemini-cli92
codex88
github-copilot88
claude-code88
cursor86
// ✅ ALWAYS: Create const object first, then extract type
const STATUS = {
ACTIVE: "active",
INACTIVE: "inactive",
PENDING: "pending",
} as const;
type Status = (typeof STATUS)[keyof typeof STATUS];
// ❌ NEVER: Direct union types
type Status = "active" | "inactive" | "pending";
Why? Single source of truth, runtime values, autocomplete, easier refactoring.
// ✅ ALWAYS: One level depth, nested objects → dedicated interface
interface UserAddress {
street: string;
city: string;
}
interface User {
id: string;
name: string;
address: UserAddress; // Reference, not inline
}
interface Admin extends User {
permissions: string[];
}
// ❌ NEVER: Inline nested objects
interface User {
address: { street: string; city: string }; // NO!
}
any// ✅ Use unknown for truly unknown types
function parse(input: unknown): User {
if (isUser(input)) return input;
throw new Error("Invalid input");
}
// ✅ Use generics for flexible types
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
// ❌ NEVER
function parse(input: any): any { }
Pick<User, "id" | "name"> // Select fields
Omit<User, "id"> // Exclude fields
Partial<User> // All optional
Required<User> // All required
Readonly<User> // All readonly
Record<string, User> // Object type
Extract<Union, "a" | "b"> // Extract from union
Exclude<Union, "a"> // Exclude from union
NonNullable<T | null> // Remove null/undefined
ReturnType<typeof fn> // Function return type
Parameters<typeof fn> // Function params tuple
function isUser(value: unknown): value is User {
return (
typeof value === "object" &&
value !== null &&
"id" in value &&
"name" in value
);
}
Do not model semantically coupled props as independent optionals — this allows invalid half-states that compile but break at runtime. Use discriminated unions with never to make invalid combinations impossible.
// ❌ BEFORE: Independent optionals — half-states allowed
interface PaginationProps {
onPageChange?: (page: number) => void;
pageSize?: number;
currentPage?: number;
}
// ✅ AFTER: Discriminated union — shape is all-or-nothing
type ControlledPagination = {
controlled: true;
currentPage: number;
pageSize: number;
onPageChange: (page: number) => void;
};
type UncontrolledPagination = {
controlled: false;
currentPage?: never;
pageSize?: never;
onPageChange?: never;
};
type PaginationProps = ControlledPagination | UncontrolledPagination;
Key rule: If two or more props are only meaningful together, they belong to the same discriminated union branch. Mixing them as independent optionals shifts correctness responsibility from the type system to runtime guards.
import type { User } from "./types";
import { createUser, type Config } from "./utils";
Weekly Installs
110
Repository
GitHub Stars
13.4K
First Seen
Jan 21, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode97
gemini-cli92
codex88
github-copilot88
claude-code88
cursor86
Node.js 环境配置指南:多环境管理、类型安全与最佳实践
10,500 周安装