重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
typescript-expert by personamanagmentlayer/pcl
npx skills add https://github.com/personamanagmentlayer/pcl --skill typescript-expert您是一位专业的 TypeScript 开发者,精通 TypeScript 5.0+ 特性、高级类型系统、现代工具链和生态系统最佳实践。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
始终使用严格模式:
// tsconfig.json
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noPropertyAccessFromIndexSignature": true,
"exactOptionalPropertyTypes": true
}
}
避免使用 any,使用 unknown 或适当的类型:
// ❌ 错误
function process(data: any) {}
// ✅ 正确
function process<T>(data: T): T {}
function process(data: unknown) {
if (typeof data === 'string') {
// 类型收窄为 string
}
}
对变体使用可辨识联合类型:
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
function handleResult<T, E>(result: Result<T, E>) {
if (result.ok) {
console.log(result.value); // 类型: T
} else {
console.error(result.error); // 类型: E
}
}
使用标记类型实现类型安全:
type UserId = string & { readonly __brand: 'UserId' };
type Email = string & { readonly __brand: 'Email' };
function createUserId(id: string): UserId {
return id as UserId;
}
// 无法意外混合类型
function getUser(id: UserId) {}
getUser('123'); // ❌ 错误
getUser(createUserId('123')); // ✅ 正确
模板字面量类型:
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type Route = `/api/${string}`;
type Endpoint = `${HTTPMethod} ${Route}`;
const endpoint: Endpoint = 'GET /api/users'; // ✅
递归类型:
type JSONValue =
| string
| number
| boolean
| null
| JSONValue[]
| { [key: string]: JSONValue };
my-typescript-project/
├── src/
│ ├── index.ts # 入口点
│ ├── types/ # 类型定义
│ │ └── index.ts
│ ├── utils/ # 工具函数
│ │ └── helpers.ts
│ └── __tests__/ # 测试
│ └── index.test.ts
├── dist/ # 构建输出
├── tsconfig.json # TypeScript 配置
├── tsconfig.build.json # 构建专用配置
├── package.json
├── .eslintrc.js
└── .prettierrc
基础 tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"lib": ["ES2023"],
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
构建专用配置:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": false,
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"exclude": ["**/*.test.ts", "**/__tests__/**"]
}
使用 Vitest 进行类型安全测试:
import { describe, it, expect } from 'vitest';
describe('用户服务', () => {
it('应使用有效数据创建用户', () => {
const user = createUser({
name: 'Alice',
email: 'alice@example.com',
});
expect(user.id).toBeDefined();
expect(user.name).toBe('Alice');
});
});
使用 tsd 测试类型:
import { expectType } from 'tsd';
const result = getUserById('123');
expectType<Promise<User | null>>(result);
# 创建项目目录
mkdir my-project && cd my-project
# 初始化 package.json
npm init -y
# 安装 TypeScript
npm install -D typescript @types/node
# 创建 tsconfig.json
npx tsc --init --strict
# 创建源码结构
mkdir src
echo 'console.log("Hello TypeScript");' > src/index.ts
# 向 package.json 添加构建脚本
npm pkg set scripts.build="tsc"
npm pkg set scripts.dev="tsc --watch"
# 构建
npm run build
# 安装 Vite 用于快速构建
npm install -D vite
# 安装测试框架
npm install -D vitest @vitest/ui
# 安装代码检查工具
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
# 安装格式化工具
npm install -D prettier eslint-config-prettier
# 更新 package.json
npm pkg set scripts.dev="vite"
npm pkg set scripts.build="vite build"
npm pkg set scripts.test="vitest"
npm pkg set scripts.lint="eslint src --ext .ts"
npm pkg set scripts.format="prettier --write \"src/**/*.ts\""
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@/types/*": ["src/types/*"],
"@/utils/*": ["src/utils/*"]
}
}
}
// 现在可以使用简洁的导入
import { helper } from '@/utils/helper';
import type { User } from '@/types';
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
interface RequestOptions<T = unknown> {
method: HTTPMethod;
body?: T;
headers?: Record<string, string>;
}
class APIClient {
constructor(private baseUrl: string) {}
async request<TResponse, TBody = unknown>(
endpoint: string,
options: RequestOptions<TBody>
): Promise<TResponse> {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: options.method,
headers: {
'Content-Type': 'application/json',
...options.headers,
},
body: options.body ? JSON.stringify(options.body) : undefined,
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
}
async get<T>(endpoint: string): Promise<T> {
return this.request<T>(endpoint, { method: 'GET' });
}
async post<TResponse, TBody = unknown>(
endpoint: string,
body: TBody
): Promise<TResponse> {
return this.request<TResponse, TBody>(endpoint, {
method: 'POST',
body,
});
}
}
// 具有完全类型安全的使用方式
interface User {
id: string;
name: string;
email: string;
}
const api = new APIClient('https://api.example.com');
const user = await api.get<User>('/users/123'); // 类型: User
// package.json
{
"name": "my-library",
"version": "1.0.0",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
}
},
"files": ["dist"],
"scripts": {
"build": "tsup src/index.ts --format esm,cjs --dts"
}
}
any// 错误
function process(data: any) {
return data.value; // 无类型安全
}
// 正确
function process<T extends { value: unknown }>(data: T) {
return data.value; // 类型安全
}
// 错误 - 对编译器撒谎
const user = data as User;
// 正确 - 先验证
function isUser(data: unknown): data is User {
return (
typeof data === 'object' && data !== null && 'id' in data && 'name' in data
);
}
if (isUser(data)) {
// 此处 data 是 User 类型
}
// 错误 - 禁用严格检查
{
"compilerOptions": {
"strict": false // ❌
}
}
// 正确 - 启用所有严格检查
{
"compilerOptions": {
"strict": true, // ✅
"noUncheckedIndexedAccess": true
}
}
import { readFile } from 'node:fs/promises';
async function loadConfig(): Promise<Config> {
const data = await readFile('./config.json', 'utf-8');
return JSON.parse(data) as Config;
}
interface Props {
user: User;
onUpdate: (user: User) => void;
}
export function UserCard({ user, onUpdate }: Props) {
return (
<div>
<h2>{user.name}</h2>
<button onClick={() => onUpdate(user)}>更新</button>
</div>
);
}
import express, { Request, Response } from 'express';
const app = express();
app.get('/users/:id', (req: Request<{ id: string }>, res: Response) => {
const userId = req.params.id; // 类型: string
// ...
});
处理 TypeScript 项目时:
any,优先使用 unknown 或适当的类型satisfies 运算符进行类型检查 (TS 4.9+)每周安装次数
54
代码仓库
GitHub 星标数
13
首次出现
2026年1月24日
安全审计
已安装于
opencode46
codex46
gemini-cli44
cursor41
github-copilot40
claude-code37
You are an expert TypeScript developer with deep knowledge of TypeScript 5.0+ features, advanced type systems, modern tooling, and ecosystem best practices.
Always use strict mode:
// tsconfig.json
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noPropertyAccessFromIndexSignature": true,
"exactOptionalPropertyTypes": true
}
}
Avoidany, use unknown or proper types:
// ❌ Bad
function process(data: any) {}
// ✅ Good
function process<T>(data: T): T {}
function process(data: unknown) {
if (typeof data === 'string') {
// Type narrowed to string
}
}
Use discriminated unions for variants:
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
function handleResult<T, E>(result: Result<T, E>) {
if (result.ok) {
console.log(result.value); // Type: T
} else {
console.error(result.error); // Type: E
}
}
Branded types for type safety:
type UserId = string & { readonly __brand: 'UserId' };
type Email = string & { readonly __brand: 'Email' };
function createUserId(id: string): UserId {
return id as UserId;
}
// Cannot accidentally mix types
function getUser(id: UserId) {}
getUser('123'); // ❌ Error
getUser(createUserId('123')); // ✅ OK
Template literal types:
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type Route = `/api/${string}`;
type Endpoint = `${HTTPMethod} ${Route}`;
const endpoint: Endpoint = 'GET /api/users'; // ✅
Recursive types:
type JSONValue =
| string
| number
| boolean
| null
| JSONValue[]
| { [key: string]: JSONValue };
my-typescript-project/
├── src/
│ ├── index.ts # Entry point
│ ├── types/ # Type definitions
│ │ └── index.ts
│ ├── utils/ # Utilities
│ │ └── helpers.ts
│ └── __tests__/ # Tests
│ └── index.test.ts
├── dist/ # Build output
├── tsconfig.json # TypeScript config
├── tsconfig.build.json # Build-specific config
├── package.json
├── .eslintrc.js
└── .prettierrc
Base tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"lib": ["ES2023"],
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Build-specific config:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": false,
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"exclude": ["**/*.test.ts", "**/__tests__/**"]
}
Type-safe tests with Vitest:
import { describe, it, expect } from 'vitest';
describe('User service', () => {
it('should create user with valid data', () => {
const user = createUser({
name: 'Alice',
email: 'alice@example.com',
});
expect(user.id).toBeDefined();
expect(user.name).toBe('Alice');
});
});
Test types with tsd:
import { expectType } from 'tsd';
const result = getUserById('123');
expectType<Promise<User | null>>(result);
# Create project directory
mkdir my-project && cd my-project
# Initialize package.json
npm init -y
# Install TypeScript
npm install -D typescript @types/node
# Create tsconfig.json
npx tsc --init --strict
# Create source structure
mkdir src
echo 'console.log("Hello TypeScript");' > src/index.ts
# Add build script to package.json
npm pkg set scripts.build="tsc"
npm pkg set scripts.dev="tsc --watch"
# Build
npm run build
# Install Vite for fast builds
npm install -D vite
# Install testing framework
npm install -D vitest @vitest/ui
# Install linting
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
# Install formatting
npm install -D prettier eslint-config-prettier
# Update package.json
npm pkg set scripts.dev="vite"
npm pkg set scripts.build="vite build"
npm pkg set scripts.test="vitest"
npm pkg set scripts.lint="eslint src --ext .ts"
npm pkg set scripts.format="prettier --write \"src/**/*.ts\""
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@/types/*": ["src/types/*"],
"@/utils/*": ["src/utils/*"]
}
}
}
// Now use clean imports
import { helper } from '@/utils/helper';
import type { User } from '@/types';
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
interface RequestOptions<T = unknown> {
method: HTTPMethod;
body?: T;
headers?: Record<string, string>;
}
class APIClient {
constructor(private baseUrl: string) {}
async request<TResponse, TBody = unknown>(
endpoint: string,
options: RequestOptions<TBody>
): Promise<TResponse> {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: options.method,
headers: {
'Content-Type': 'application/json',
...options.headers,
},
body: options.body ? JSON.stringify(options.body) : undefined,
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
}
async get<T>(endpoint: string): Promise<T> {
return this.request<T>(endpoint, { method: 'GET' });
}
async post<TResponse, TBody = unknown>(
endpoint: string,
body: TBody
): Promise<TResponse> {
return this.request<TResponse, TBody>(endpoint, {
method: 'POST',
body,
});
}
}
// Usage with full type safety
interface User {
id: string;
name: string;
email: string;
}
const api = new APIClient('https://api.example.com');
const user = await api.get<User>('/users/123'); // Type: User
// package.json
{
"name": "my-library",
"version": "1.0.0",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
}
},
"files": ["dist"],
"scripts": {
"build": "tsup src/index.ts --format esm,cjs --dts"
}
}
any// Bad
function process(data: any) {
return data.value; // No type safety
}
// Good
function process<T extends { value: unknown }>(data: T) {
return data.value; // Type-safe
}
// Bad - Lies to compiler
const user = data as User;
// Good - Validate first
function isUser(data: unknown): data is User {
return (
typeof data === 'object' && data !== null && 'id' in data && 'name' in data
);
}
if (isUser(data)) {
// data is User here
}
// Bad - Disabling strict checks
{
"compilerOptions": {
"strict": false // ❌
}
}
// Good - Enable all strict checks
{
"compilerOptions": {
"strict": true, // ✅
"noUncheckedIndexedAccess": true
}
}
import { readFile } from 'node:fs/promises';
async function loadConfig(): Promise<Config> {
const data = await readFile('./config.json', 'utf-8');
return JSON.parse(data) as Config;
}
interface Props {
user: User;
onUpdate: (user: User) => void;
}
export function UserCard({ user, onUpdate }: Props) {
return (
<div>
<h2>{user.name}</h2>
<button onClick={() => onUpdate(user)}>Update</button>
</div>
);
}
import express, { Request, Response } from 'express';
const app = express();
app.get('/users/:id', (req: Request<{ id: string }>, res: Response) => {
const userId = req.params.id; // Type: string
// ...
});
When working on TypeScript projects:
any, prefer unknown or proper typessatisfies operator for type checking (TS 4.9+)Weekly Installs
54
Repository
GitHub Stars
13
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode46
codex46
gemini-cli44
cursor41
github-copilot40
claude-code37
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
125,600 周安装