typescript-quality
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTypeScript Quality - Quick Reference
TypeScript代码质量 - 快速参考
When NOT to Use This Skill
何时不使用本技能
- SonarQube integration - Use skill
sonarqube - Test configuration - Use skill
vitest - Security scanning - Use security skills
- React-specific patterns - Use skill
react
Deep Knowledge: Usewith technology:mcp__documentation__fetch_docsortypescriptfor comprehensive documentation.biome
- SonarQube集成 - 使用技能
sonarqube - 测试配置 - 使用技能
vitest - 安全扫描 - 使用安全类技能
- React特定模式 - 使用技能
react
深入了解: 使用工具,指定技术为mcp__documentation__fetch_docs或typescript以获取完整文档。biome
Tool Comparison
工具对比
| Tool | Speed | Type-aware | Configuration |
|---|---|---|---|
| Biome | Fastest | No | Minimal |
| ESLint | Slower | Yes (with TS) | Extensive |
| TypeScript | N/A | Yes | tsconfig.json |
Recommendation: Use Biome for formatting + basic linting, ESLint for type-aware rules.
| 工具 | 速度 | 类型感知 | 配置复杂度 |
|---|---|---|---|
| Biome | 最快 | 无 | 极简 |
| ESLint | 较慢 | 是(搭配TS) | 丰富 |
| TypeScript | 不适用 | 是 | tsconfig.json |
推荐方案: 使用Biome进行格式化及基础代码检查,使用ESLint实现类型感知规则。
Biome Setup (Recommended)
Biome搭建(推荐)
Installation
安装
bash
npm install -D @biomejs/biome
npx biome initbash
npm install -D @biomejs/biome
npx biome initbiome.json
biome.json
json
{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"organizeImports": { "enabled": true },
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noExcessiveCognitiveComplexity": {
"level": "warn",
"options": { "maxAllowedComplexity": 15 }
}
},
"suspicious": {
"noExplicitAny": "error",
"noImplicitAnyLet": "error"
},
"style": {
"noNonNullAssertion": "warn",
"useConst": "error"
}
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "es5",
"semicolons": "always"
}
}
}json
{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"organizeImports": { "enabled": true },
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noExcessiveCognitiveComplexity": {
"level": "warn",
"options": { "maxAllowedComplexity": 15 }
}
},
"suspicious": {
"noExplicitAny": "error",
"noImplicitAnyLet": "error"
},
"style": {
"noNonNullAssertion": "warn",
"useConst": "error"
}
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "es5",
"semicolons": "always"
}
}
}Commands
命令
bash
undefinedbash
undefinedCheck all
检查所有文件
npx biome check .
npx biome check .
Fix auto-fixable
自动修复可修复问题
npx biome check --write .
npx biome check --write .
Format only
仅格式化
npx biome format --write .
npx biome format --write .
Lint only
仅检查代码规范
npx biome lint .
npx biome lint .
CI mode (no write)
CI模式(不写入修改)
npx biome ci .
undefinednpx biome ci .
undefinedESLint Setup (Type-aware)
ESLint搭建(类型感知)
Installation
安装
bash
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-pluginbash
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugineslint.config.js (Flat Config - ESLint 9+)
eslint.config.js(扁平配置 - ESLint 9+)
javascript
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.strictTypeChecked,
...tseslint.configs.stylisticTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
// Type safety
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unsafe-assignment': 'error',
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-return': 'error',
// Best practices
'@typescript-eslint/explicit-function-return-type': 'warn',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/no-misused-promises': 'error',
// Code quality
'complexity': ['warn', { max: 10 }],
'max-depth': ['warn', { max: 4 }],
'max-lines-per-function': ['warn', { max: 50 }],
},
},
{
ignores: ['dist/', 'node_modules/', '*.config.js'],
}
);javascript
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.strictTypeChecked,
...tseslint.configs.stylisticTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
// 类型安全
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unsafe-assignment': 'error',
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-return': 'error',
// 最佳实践
'@typescript-eslint/explicit-function-return-type': 'warn',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/no-misused-promises': 'error',
// 代码质量
'complexity': ['warn', { max: 10 }],
'max-depth': ['warn', { max: 4 }],
'max-lines-per-function': ['warn', { max: 50 }],
},
},
{
ignores: ['dist/', 'node_modules/', '*.config.js'],
}
);Commands
命令
bash
undefinedbash
undefinedLint
检查代码规范
npx eslint .
npx eslint .
Fix auto-fixable
自动修复可修复问题
npx eslint --fix .
npx eslint --fix .
Show rule details
查看规则详情
npx eslint --print-config src/index.ts
undefinednpx eslint --print-config src/index.ts
undefinedTypeScript Strict Mode
TypeScript严格模式
tsconfig.json (Maximum Strictness)
tsconfig.json(最高严格程度)
json
{
"compilerOptions": {
// Strict type checking
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noPropertyAccessFromIndexSignature": true,
// Additional checks
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
// Module resolution
"moduleResolution": "bundler",
"module": "ESNext",
"target": "ES2022",
// Interop
"esModuleInterop": true,
"isolatedModules": true,
"verbatimModuleSyntax": true
}
}json
{
"compilerOptions": {
// 严格类型检查
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noPropertyAccessFromIndexSignature": true,
// 额外检查
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
// 模块解析
"moduleResolution": "bundler",
"module": "ESNext",
"target": "ES2022",
// 互操作性
"esModuleInterop": true,
"isolatedModules": true,
"verbatimModuleSyntax": true
}
}Key Strict Flags Explained
关键严格模式标志说明
| Flag | Effect | Example |
|---|---|---|
| Array access returns | |
| | Can't assign |
| Forces bracket notation for index signatures | |
| 标志 | 作用 | 示例 |
|---|---|---|
| 数组访问返回 | |
| | 不能显式赋值 |
| 强制对索引签名使用方括号语法 | 使用 |
Common Code Smells & Fixes
常见代码异味及修复方案
1. Excessive any
Usage
any1. 过度使用any
类型
anytypescript
// BAD
function process(data: any): any {
return data.value;
}
// GOOD
interface DataItem {
value: string;
}
function process(data: DataItem): string {
return data.value;
}
// GOOD - When truly unknown
function process(data: unknown): string {
if (typeof data === 'object' && data !== null && 'value' in data) {
return String((data as { value: unknown }).value);
}
throw new Error('Invalid data');
}typescript
// BAD
function process(data: any): any {
return data.value;
}
// GOOD
interface DataItem {
value: string;
}
function process(data: DataItem): string {
return data.value;
}
// GOOD - 当类型确实未知时
function process(data: unknown): string {
if (typeof data === 'object' && data !== null && 'value' in data) {
return String((data as { value: unknown }).value);
}
throw new Error('Invalid data');
}2. Type Assertions Overuse
2. 过度使用类型断言
typescript
// BAD
const user = response.data as User;
// GOOD - Use type guards
function isUser(data: unknown): data is User {
return (
typeof data === 'object' &&
data !== null &&
'id' in data &&
'email' in data
);
}
if (isUser(response.data)) {
// response.data is User here
}
// GOOD - Use Zod for runtime validation
import { z } from 'zod';
const UserSchema = z.object({
id: z.string(),
email: z.string().email(),
});
const user = UserSchema.parse(response.data);typescript
// BAD
const user = response.data as User;
// GOOD - 使用类型守卫
function isUser(data: unknown): data is User {
return (
typeof data === 'object' &&
data !== null &&
'id' in data &&
'email' in data
);
}
if (isUser(response.data)) {
// 此处response.data类型为User
}
// GOOD - 使用Zod进行运行时验证
import { z } from 'zod';
const UserSchema = z.object({
id: z.string(),
email: z.string().email(),
});
const user = UserSchema.parse(response.data);3. Non-null Assertion
3. 非空断言
typescript
// BAD
const element = document.getElementById('app')!;
// GOOD
const element = document.getElementById('app');
if (!element) {
throw new Error('App element not found');
}
// GOOD - Optional chaining when appropriate
const value = element?.textContent ?? 'default';typescript
// BAD
const element = document.getElementById('app')!;
// GOOD
const element = document.getElementById('app');
if (!element) {
throw new Error('App element not found');
}
// GOOD - 适当时使用可选链
const value = element?.textContent ?? 'default';4. Complex Conditionals
4. 复杂条件判断
typescript
// BAD
if (user && user.isActive && user.role === 'admin' && !user.suspended) {
// ...
}
// GOOD - Extract to function
function canAccessAdmin(user: User | null): user is User {
return (
user !== null &&
user.isActive &&
user.role === 'admin' &&
!user.suspended
);
}
if (canAccessAdmin(user)) {
// ...
}typescript
// BAD
if (user && user.isActive && user.role === 'admin' && !user.suspended) {
// ...
}
// GOOD - 提取为函数
function canAccessAdmin(user: User | null): user is User {
return (
user !== null &&
user.isActive &&
user.role === 'admin' &&
!user.suspended
);
}
if (canAccessAdmin(user)) {
// ...
}5. Long Functions
5. 过长函数
typescript
// BAD - 100+ line function
async function processOrder(order: Order) {
// validation
// calculation
// database operations
// notifications
// logging
}
// GOOD - Split responsibilities
async function processOrder(order: Order) {
validateOrder(order);
const total = calculateTotal(order);
await saveOrder(order, total);
await notifyUser(order);
logOrderProcessed(order);
}typescript
// BAD - 超过100行的函数
async function processOrder(order: Order) {
// 验证
// 计算
// 数据库操作
// 通知
// 日志
}
// GOOD - 拆分职责
async function processOrder(order: Order) {
validateOrder(order);
const total = calculateTotal(order);
await saveOrder(order, total);
await notifyUser(order);
logOrderProcessed(order);
}Pre-commit Setup
提交前检查配置
package.json Scripts
package.json脚本
json
{
"scripts": {
"lint": "biome check .",
"lint:fix": "biome check --write .",
"typecheck": "tsc --noEmit",
"quality": "npm run typecheck && npm run lint"
}
}json
{
"scripts": {
"lint": "biome check .",
"lint:fix": "biome check --write .",
"typecheck": "tsc --noEmit",
"quality": "npm run typecheck && npm run lint"
}
}Husky + lint-staged
Husky + lint-staged
bash
npm install -D husky lint-staged
npx husky initjson
// package.json
{
"lint-staged": {
"*.{ts,tsx,js,jsx}": [
"biome check --write --no-errors-on-unmatched"
]
}
}bash
undefinedbash
npm install -D husky lint-staged
npx husky initjson
// package.json
{
"lint-staged": {
"*.{ts,tsx,js,jsx}": [
"biome check --write --no-errors-on-unmatched"
]
}
}bash
undefined.husky/pre-commit
.husky/pre-commit
npx lint-staged
undefinednpx lint-staged
undefinedVS Code Settings
VS Code设置
json
// .vscode/settings.json
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit",
"quickfix.biome": "explicit"
},
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}json
// .vscode/settings.json
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit",
"quickfix.biome": "explicit"
},
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}Quality Metrics Targets
代码质量指标目标
| Metric | Target | Tool |
|---|---|---|
| Cyclomatic Complexity | < 10 | ESLint complexity rule |
| Cognitive Complexity | < 15 | Biome/SonarQube |
| Function Length | < 50 lines | ESLint max-lines-per-function |
| File Length | < 300 lines | ESLint max-lines |
| Nesting Depth | < 4 levels | ESLint max-depth |
| Parameters | < 4 | ESLint max-params |
| 指标 | 目标值 | 工具 |
|---|---|---|
| 圈复杂度 | < 10 | ESLint complexity规则 |
| 认知复杂度 | < 15 | Biome/SonarQube |
| 函数长度 | < 50行 | ESLint max-lines-per-function |
| 文件长度 | < 300行 | ESLint max-lines |
| 嵌套深度 | < 4层 | ESLint max-depth |
| 参数数量 | < 4个 | ESLint max-params |
Anti-Patterns
反模式
| Anti-Pattern | Why It's Bad | Correct Approach |
|---|---|---|
| Defeats type safety | Use proper types or |
| Runtime errors | Use type guards or Zod |
| Potential runtime null | Proper null checking |
| Disabling lint rules inline | Technical debt | Fix the issue or configure globally |
| Hides real errors | Use |
| No strict mode | Weaker guarantees | Enable all strict flags |
| 反模式 | 危害 | 正确做法 |
|---|---|---|
到处使用 | 失去类型安全保障 | 使用正确类型或 |
滥用 | 可能导致运行时错误 | 使用类型守卫或Zod |
滥用 | 可能出现空值运行时错误 | 正确进行空值检查 |
| 内联禁用检查规则 | 积累技术债务 | 修复问题或全局配置规则 |
使用 | 隐藏真实错误 | 使用 |
| 未启用严格模式 | 类型保障薄弱 | 启用所有严格模式标志 |
Quick Troubleshooting
快速排查指南
| Issue | Likely Cause | Solution |
|---|---|---|
| ESLint slow on large projects | Type-aware rules expensive | Use project references, cache |
| Biome conflicts with ESLint | Both trying to format | Use Biome for format, ESLint for type rules |
| TypeScript error not caught by lint | Need type-aware rule | Use typescript-eslint with projectService |
| Import order inconsistent | No auto-organize | Enable Biome organizeImports |
| Pre-commit too slow | Running on all files | Use lint-staged for changed files only |
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 大型项目中ESLint运行缓慢 | 类型感知规则开销大 | 使用项目引用、缓存机制 |
| Biome与ESLint冲突 | 两者都尝试格式化代码 | 使用Biome负责格式化,ESLint负责类型规则 |
| TypeScript错误未被检查工具捕获 | 需要类型感知规则 | 使用typescript-eslint并启用projectService |
| 导入顺序不一致 | 未启用自动整理导入 | 开启Biome的organizeImports功能 |
| 提交前检查过慢 | 对所有文件执行检查 | 使用lint-staged仅检查变更文件 |
Related Skills
相关技能
- Biome
- ESLint
- SonarQube
- Clean Code
- Biome
- ESLint
- SonarQube
- Clean Code