TypeScript开发技能Skill typescript

本技能提供TypeScript开发的专业知识,专注于为JARVIS AI助手实现类型安全,涵盖Vue组件、API路由、3D渲染和状态管理等领域,强调编译时错误预防和运行时数据验证。关键词:TypeScript,类型安全,AI助手,前端开发,全栈开发,Zod,Vue组件,API路由,3D渲染。

前端开发 0 次安装 0 次浏览 更新于 3/15/2026

name: typescript description: JARVIS AI助手的类型安全开发模式 model: sonnet risk_level: 中等 version: 1.0.0

TypeScript开发技能

文件组织: 此技能采用拆分结构。请参阅references/以获取高级模式和安全性示例。

1. 概述

此技能为JARVIS AI助手提供TypeScript专业知识,确保整个代码库的类型安全,包括Vue组件、API路由、3D渲染和状态管理。

风险级别: 中等 - 类型系统防止运行时错误,强制合约,但配置不当可能导致安全漏洞

主要用例:

  • 定义JARVIS系统数据的类型安全接口
  • 使用Zod模式进行运行时验证
  • 可重用HUD组件的通用模式
  • 严格空检查以防止崩溃

2. 核心职责

2.1 基本原则

  1. 测试驱动开发优先: 先写测试再实现 - 红、绿、重构
  2. 性能意识: 应用记忆化、懒加载和高效模式
  3. 始终启用严格模式: 启用所有严格编译器选项 - 无捷径
  4. 在边界处显式类型: 在模块边界处始终类型化函数参数和返回值
  5. 运行时验证: TypeScript类型在运行时消失 - 使用Zod处理外部数据
  6. 无任何转义舱口: 使用unknown代替any,然后用类型守卫缩小范围
  7. 默认不可变: 优先使用readonlyas const以确保数据完整性
  8. 判别联合类型: 使用标记联合类型处理状态机和错误处理
  9. 标记类型: 为ID和敏感值创建名义类型

3. 技术栈和版本

3.1 推荐版本

版本 安全性说明
typescript ^5.3.0 最新稳定版,改进类型推断
zod ^3.22.0 运行时验证,模式优先
@types/node ^20.0.0 匹配Node.js版本

3.2 编译器配置

{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "exactOptionalPropertyTypes": true,
    "noPropertyAccessFromIndexSignature": true,
    "forceConsistentCasingInFileNames": true,
    "verbatimModuleSyntax": true,
    "moduleResolution": "bundler",
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"]
  }
}

4. 实现模式

4.1 标记类型用于安全性

// types/branded.ts
declare const __brand: unique symbol

type Brand<T, B> = T & { [__brand]: B }

// ✅ 防止意外混合ID
export type UserId = Brand<string, 'UserId'>
export type SessionId = Brand<string, 'SessionId'>
export type CommandId = Brand<string, 'CommandId'>

// 带验证的工厂函数
export function createUserId(id: string): UserId {
  if (!/^usr_[a-zA-Z0-9]{16}$/.test(id)) {
    throw new Error('无效的用户ID格式')
  }
  return id as UserId
}

// ✅ 类型系统防止混合ID
function getUser(id: UserId): User { /* ... */ }
function getSession(id: SessionId): Session { /* ... */ }

// 这不会编译:
// getUser(sessionId) // 错误: SessionId不可分配给UserId

4.2 判别联合类型用于状态

// types/jarvis-state.ts

// ✅ 类型安全状态机
type JARVISState =
  | { status: 'idle' }
  | { status: 'listening'; startTime: number }
  | { status: 'processing'; commandId: CommandId }
  | { status: 'responding'; response: string; confidence: number }
  | { status: 'error'; error: JARVISError; retryCount: number }

// ✅ 穷举处理
function handleState(state: JARVISState): string {
  switch (state.status) {
    case 'idle':
      return '就绪'
    case 'listening':
      return `监听中 ${Date.now() - state.startTime}毫秒`
    case 'processing':
      return `处理中 ${state.commandId}`
    case 'responding':
      return `${state.response} (${state.confidence}%)`
    case 'error':
      return `错误: ${state.error.message}`
    default:
      // ✅ 编译时穷举检查
      const _exhaustive: never = state
      return _exhaustive
  }
}

4.3 使用Zod进行运行时验证

// schemas/command.ts
import { z } from 'zod'

// ✅ 模式优先方法
export const commandSchema = z.object({
  id: z.string().regex(/^cmd_[a-zA-Z0-9]{16}$/),
  action: z.enum(['navigate', 'control', 'query', 'configure']),
  target: z.string().min(1).max(100),
  parameters: z.record(z.unknown()).optional(),
  timestamp: z.number().int().positive(),
  priority: z.number().min(0).max(10).default(5)
})

// ✅ 从模式推断TypeScript类型
export type Command = z.infer<typeof commandSchema>

// ✅ 完整验证解析
export function parseCommand(data: unknown): Command {
  return commandSchema.parse(data)
}

// ✅ 安全解析用于错误处理
export function tryParseCommand(data: unknown): Command | null {
  const result = commandSchema.safeParse(data)
  return result.success ? result.data : null
}

4.4 HUD组件的通用模式

// ✅ 带约束的泛型 - 确保指标类型安全
interface MetricConfig<T extends Record<string, number>> {
  metrics: T
  thresholds: { [K in keyof T]: { warning: number; critical: number } }
}

type SystemMetrics = { cpu: number; memory: number }
const config: MetricConfig<SystemMetrics> = {
  metrics: { cpu: 45, memory: 72 },
  thresholds: {
    cpu: { warning: 70, critical: 90 },
    memory: { warning: 80, critical: 95 }
  }
}

4.5 类型守卫用于缩小范围

// ✅ 类型谓词用于安全缩小范围
function isSuccessResponse<T>(
  response: APIResponse<T>
): response is APIResponse<T> & { success: true; data: T } {
  return response.success && response.data !== undefined
}

// 用法 - 类型自动缩小
if (isSuccessResponse(response)) {
  return response.data // ✅ 类型为T,非T | undefined
}

4.6 JARVIS实用类型

// types/utilities.ts

// ✅ 深度只读用于不可变状态
type DeepReadonly<T> = {
  readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K]
}

// ✅ 使特定键为必需
type RequireKeys<T, K extends keyof T> = T & Required<Pick<T, K>>

// ✅ 提取事件载荷
type EventPayload<T> = T extends { payload: infer P } ? P : never

// ✅ 异步函数返回类型
type AsyncReturnType<T extends (...args: any[]) => Promise<any>> =
  T extends (...args: any[]) => Promise<infer R> ? R : never

5. 实现工作流程(测试驱动开发)

步骤1: 先写失败测试

// tests/utils/command-parser.test.ts
import { describe, it, expect } from 'vitest'
import { parseCommand } from '@/utils/command-parser'

describe('parseCommand', () => {
  it('应解析有效命令', () => {
    expect(parseCommand('open settings')).toEqual({
      action: 'open', target: 'settings', parameters: {}
    })
  })

  it('应提取参数', () => {
    expect(parseCommand('set volume to 80')).toEqual({
      action: 'set', target: 'volume', parameters: { value: 80 }
    })
  })

  it('空命令应抛出异常', () => {
    expect(() => parseCommand('')).toThrow('命令不能为空')
  })
})

步骤2: 实现最小化代码以通过测试

只写使测试通过的代码。

步骤3: 必要时重构

在保持测试通过的同时改进代码质量。

步骤4: 运行完整验证

npx vitest run              # 单元测试
npx eslint . --ext .ts,.tsx # 代码检查
npx tsc --noEmit            # 类型检查

6. 性能模式

6.1 记忆化

// ❌ 坏 - 每次渲染都重新计算
const processed = data.map(item => heavyTransform(item))

// ✅ 好 - 记忆化计算
import { computed } from 'vue'
const processed = computed(() => data.value.map(item => heavyTransform(item)))

6.2 懒加载

// ❌ 坏 - 提前加载所有内容
import { HeavyChart } from '@/components/HeavyChart'

// ✅ 好 - 懒加载重型组件
import { defineAsyncComponent } from 'vue'
const HeavyChart = defineAsyncComponent(() => import('@/components/HeavyChart'))

6.3 防抖/节流

// ❌ 坏 - 每次按键都调用API
const handleSearch = (q: string) => fetchResults(q)

// ✅ 好 - 防抖搜索(300毫秒延迟)
import { useDebounceFn } from '@vueuse/core'
const debouncedSearch = useDebounceFn((q: string) => fetchResults(q), 300)

6.4 高效数据结构

// ❌ 坏 - O(n)查找
const user = users.find(u => u.id === id)

// ✅ 好 - 使用Map进行O(1)查找
const userMap = new Map(users.map(u => [u.id, u]))
const user = userMap.get(id)

// ✅ 好 - 使用Set进行O(1)成员检查
const allowed = new Set(['read', 'write'])
const hasAccess = allowed.has(permission)

6.5 并行异步操作

// ❌ 坏 - 顺序执行(总时间=时间之和)
const user = await fetchUser()
const metrics = await fetchMetrics()

// ✅ 好 - 并行执行(总时间=最大时间)
const [user, metrics] = await Promise.all([fetchUser(), fetchMetrics()])

// ✅ 好 - 带错误处理
const results = await Promise.allSettled([fetchUser(), fetchMetrics()])

7. 安全标准

7.1 已知漏洞

TypeScript本身有强大的安全记录。主要风险来自:

风险领域 描述 缓解措施
类型擦除 类型在运行时不存在 使用Zod进行外部数据验证
任意类型 禁用类型检查 启用noImplicitAny,使用unknown
类型断言 可绕过类型系统 避免as,使用类型守卫

7.2 OWASP Top 10覆盖

OWASP类别 TypeScript缓解措施
A03 注入 类型化API防止查询中的字符串插值
A04 不安全设计 强类型化强制执行安全接口
A08 软件完整性 编译时检查在部署前捕获错误

7.3 安全类型模式

// ❌ 危险 - 类型断言绕过安全性
const userData = apiResponse as User

// ✅ 安全 - 运行时验证
const userData = userSchema.parse(apiResponse)

// ❌ 危险 - any禁用所有检查
function process(data: any) { /* ... */ }

// ✅ 安全 - unknown需要缩小范围
function process(data: unknown) {
  const validated = commandSchema.parse(data)
  // 现在安全类型化
}

8. 测试与质量

// 使用vitest进行类型测试
import { expectTypeOf } from 'vitest'

describe('类型安全', () => {
  it('应强制标记类型', () => {
    expectTypeOf(createUserId('usr_1234567890123456')).toEqualTypeOf<UserId>()
  })
})

// 模式验证测试
describe('命令模式', () => {
  it('应拒绝无效ID', () => {
    expect(() => commandSchema.parse({ id: 'invalid' })).toThrow()
  })

  it('应接受有效命令', () => {
    const result = commandSchema.parse({ id: 'cmd_1234567890123456', action: 'query' })
    expect(result.action).toBe('query')
  })
})

9. 常见错误和反模式

9.1 关键安全反模式

绝不:使用类型断言处理外部数据

// ❌ 危险 - 无运行时验证
const user = JSON.parse(data) as User

// ✅ 安全 - 在运行时验证
const user = userSchema.parse(JSON.parse(data))

绝不:忽略空/未定义检查

// ❌ 危险 - 如果未定义则运行时崩溃
function getConfig(key: string) {
  return config[key].value  // 可能未定义!
}

// ✅ 安全 - 显式空处理
function getConfig(key: string): string | undefined {
  return config[key]?.value
}

绝不:使用索引签名而不检查

// ❌ 危险 - 无类型安全
const handlers: Record<string, Handler> = {}
handlers['cmd'].execute()  // 可能未定义!

// ✅ 安全 - 显式查找带检查
const handler = handlers['cmd']
if (handler) {
  handler.execute()
}

9.2 性能反模式

避免:过度类型复杂性

// ❌ 坏 - 不可读,编译慢
type DeepPartialRecord<T> = T extends object
  ? { [K in keyof T]?: DeepPartialRecord<T[K]> }
  : T extends Array<infer U>
  ? Array<DeepPartialRecord<U>>
  : T

// ✅ 好 - 简单,清晰类型
interface PartialConfig {
  theme?: Partial<ThemeConfig>
  metrics?: Partial<MetricsConfig>
}

10. 预部署清单

阶段1: 写代码前

  • [ ] 先写失败测试(测试驱动开发)
  • [ ] 为新功能定义类型和接口
  • [ ] 规划外部数据的Zod模式
  • [ ] 识别性能关键路径
  • [ ] 查看代码库中的现有模式

阶段2: 实现期间

  • [ ] 在tsconfig中启用strict: true
  • [ ] 启用noUncheckedIndexedAccess: true
  • [ ] 启用noImplicitAny: true
  • [ ] 生产代码中无any类型
  • [ ] 所有外部数据用Zod验证
  • [ ] 敏感ID使用标记类型
  • [ ] 状态机使用判别联合类型
  • [ ] 昂贵计算应用记忆化
  • [ ] 重型组件使用懒加载
  • [ ] 查找使用高效数据结构(Map/Set)

阶段3: 提交前

  • [ ] 所有测试通过(npx vitest run
  • [ ] 无代码检查错误(npx eslint .
  • [ ] 无TypeScript错误(npx tsc --noEmit
  • [ ] 所有API输入在运行时验证
  • [ ] 外部数据无类型断言
  • [ ] 应用性能模式于需要处

11. 总结

TypeScript为JARVIS开发提供编译时安全性:

  1. 严格配置: 启用所有严格选项以最大化安全性
  2. 运行时验证: 类型在运行时消失 - 使用Zod
  3. 标记类型: 防止混合ID和敏感值
  4. 类型守卫: 使用谓词安全缩小unknown数据范围

记住: TypeScript仅在编译时检查。与外部数据的每个边界必须有运行时验证。


参考文献:

  • references/advanced-patterns.md - 复杂类型模式
  • references/security-examples.md - 安全类型化实践