typescript by martinholovsky/claude-skills-generator
npx skills add https://github.com/martinholovsky/claude-skills-generator --skill typescript文件组织:此技能采用分割结构。高级模式和安全示例请参阅
references/目录。
此技能为 JARVIS AI 助手提供 TypeScript 专业知识,确保包括 Vue 组件、API 路由、3D 渲染和状态管理在内的整个代码库的类型安全。
风险等级:中等 - 类型系统可防止运行时错误,强制执行契约,但配置错误可能导致安全漏洞。
主要用例:
unknown 而非 any,然后使用类型守卫进行收窄广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
readonly 和 as const 以保证数据完整性| 包 | 版本 | 安全说明 |
|---|---|---|
| typescript | ^5.3.0 | 最新稳定版,改进了类型推断 |
| zod | ^3.22.0 | 运行时验证,模式优先 |
| @types/node | ^20.0.0 | 匹配 Node.js 版本 |
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"exactOptionalPropertyTypes": true,
"noPropertyAccessFromIndexSignature": true,
"forceConsistentCasingInFileNames": true,
"verbatimModuleSyntax": true,
"moduleResolution": "bundler",
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"]
}
}
// 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('Invalid user ID format')
}
return id as UserId
}
// ✅ 类型系统防止混淆 ID
function getUser(id: UserId): User { /* ... */ }
function getSession(id: SessionId): Session { /* ... */ }
// 这将无法编译:
// getUser(sessionId) // 错误:SessionId 无法赋值给 UserId
// 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 'Ready'
case 'listening':
return `Listening for ${Date.now() - state.startTime}ms`
case 'processing':
return `Processing ${state.commandId}`
case 'responding':
return `${state.response} (${state.confidence}%)`
case 'error':
return `Error: ${state.error.message}`
default:
// ✅ 编译时穷尽性检查
const _exhaustive: never = state
return _exhaustive
}
}
// 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
}
// ✅ 带约束的泛型 - 确保指标的类型安全
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 }
}
}
// ✅ 用于安全收窄的类型谓词
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
}
// 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
// tests/utils/command-parser.test.ts
import { describe, it, expect } from 'vitest'
import { parseCommand } from '@/utils/command-parser'
describe('parseCommand', () => {
it('should parse valid command', () => {
expect(parseCommand('open settings')).toEqual({
action: 'open', target: 'settings', parameters: {}
})
})
it('should extract parameters', () => {
expect(parseCommand('set volume to 80')).toEqual({
action: 'set', target: 'volume', parameters: { value: 80 }
})
})
it('should throw on empty command', () => {
expect(() => parseCommand('')).toThrow('Command cannot be empty')
})
})
仅编写使测试通过所需的代码。
在保持测试通过的同时提高代码质量。
npx vitest run # 单元测试
npx eslint . --ext .ts,.tsx # 代码检查
npx tsc --noEmit # 类型检查
// ❌ 差 - 每次渲染都重新计算
const processed = data.map(item => heavyTransform(item))
// ✅ 好 - 记忆化计算
import { computed } from 'vue'
const processed = computed(() => data.value.map(item => heavyTransform(item)))
// ❌ 差 - 预先加载所有内容
import { HeavyChart } from '@/components/HeavyChart'
// ✅ 好 - 懒加载重型组件
import { defineAsyncComponent } from 'vue'
const HeavyChart = defineAsyncComponent(() => import('@/components/HeavyChart'))
// ❌ 差 - 每次按键都调用 API
const handleSearch = (q: string) => fetchResults(q)
// ✅ 好 - 防抖搜索(300 毫秒延迟)
import { useDebounceFn } from '@vueuse/core'
const debouncedSearch = useDebounceFn((q: string) => fetchResults(q), 300)
// ❌ 差 - 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)
// ❌ 差 - 顺序执行(总时间 = 各时间之和)
const user = await fetchUser()
const metrics = await fetchMetrics()
// ✅ 好 - 并行执行(总时间 = 各时间最大值)
const [user, metrics] = await Promise.all([fetchUser(), fetchMetrics()])
// ✅ 好 - 带错误处理
const results = await Promise.allSettled([fetchUser(), fetchMetrics()])
TypeScript 本身有良好的安全记录。主要风险来自:
| 风险领域 | 描述 | 缓解措施 |
|---|---|---|
| 类型擦除 | 类型在运行时不存在 | 使用 Zod 验证外部数据 |
| Any 类型 | 禁用类型检查 | 启用 noImplicitAny,使用 unknown |
| 类型断言 | 可绕过类型系统 | 避免使用 as,改用类型守卫 |
| OWASP 类别 | TypeScript 缓解措施 |
|---|---|
| A03 注入 | 类型化 API 防止查询中的字符串插值 |
| A04 不安全设计 | 强类型强制执行安全接口 |
| A08 软件完整性 | 编译时检查在部署前捕获错误 |
// ❌ 危险 - 类型断言绕过安全检查
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)
// 现在已安全类型化
}
// 使用 vitest 进行类型测试
import { expectTypeOf } from 'vitest'
describe('Type Safety', () => {
it('should enforce branded types', () => {
expectTypeOf(createUserId('usr_1234567890123456')).toEqualTypeOf<UserId>()
})
})
// 模式验证测试
describe('Command Schema', () => {
it('should reject invalid IDs', () => {
expect(() => commandSchema.parse({ id: 'invalid' })).toThrow()
})
it('should accept valid commands', () => {
const result = commandSchema.parse({ id: 'cmd_1234567890123456', action: 'query' })
expect(result.action).toBe('query')
})
})
// ❌ 危险 - 无运行时验证
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()
}
// ❌ 差 - 不可读,编译缓慢
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>
}
strict: truenoUncheckedIndexedAccess: truenoImplicitAny: trueany 类型npx vitest run)npx eslint .)npx tsc --noEmit)TypeScript 为 JARVIS 开发提供编译时安全性:
unknown 数据请记住:TypeScript 仅在编译时检查。与外部数据的每个边界都必须进行运行时验证。
参考资料:
references/advanced-patterns.md - 复杂类型模式references/security-examples.md - 安全类型实践每周安装量
79
代码仓库
GitHub 星标数
32
首次出现
2026年1月20日
安全审计
安装于
codex60
gemini-cli60
opencode56
github-copilot56
cursor55
claude-code52
File Organization : This skill uses split structure. See
references/for advanced patterns and security examples.
This skill provides TypeScript expertise for the JARVIS AI Assistant, ensuring type safety across the entire codebase including Vue components, API routes, 3D rendering, and state management.
Risk Level : MEDIUM - Type system prevents runtime errors, enforces contracts, but misconfiguration can lead to security gaps
Primary Use Cases :
unknown instead of any, then narrow with type guardsreadonly and as const for data integrity| Package | Version | Security Notes |
|---|---|---|
| typescript | ^5.3.0 | Latest stable with improved type inference |
| zod | ^3.22.0 | Runtime validation, schema-first |
| @types/node | ^20.0.0 | Match Node.js version |
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"exactOptionalPropertyTypes": true,
"noPropertyAccessFromIndexSignature": true,
"forceConsistentCasingInFileNames": true,
"verbatimModuleSyntax": true,
"moduleResolution": "bundler",
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"]
}
}
// types/branded.ts
declare const __brand: unique symbol
type Brand<T, B> = T & { [__brand]: B }
// ✅ Prevent accidental mixing of IDs
export type UserId = Brand<string, 'UserId'>
export type SessionId = Brand<string, 'SessionId'>
export type CommandId = Brand<string, 'CommandId'>
// Factory functions with validation
export function createUserId(id: string): UserId {
if (!/^usr_[a-zA-Z0-9]{16}$/.test(id)) {
throw new Error('Invalid user ID format')
}
return id as UserId
}
// ✅ Type system prevents mixing IDs
function getUser(id: UserId): User { /* ... */ }
function getSession(id: SessionId): Session { /* ... */ }
// This won't compile:
// getUser(sessionId) // Error: SessionId not assignable to UserId
// types/jarvis-state.ts
// ✅ Type-safe state machine
type JARVISState =
| { status: 'idle' }
| { status: 'listening'; startTime: number }
| { status: 'processing'; commandId: CommandId }
| { status: 'responding'; response: string; confidence: number }
| { status: 'error'; error: JARVISError; retryCount: number }
// ✅ Exhaustive handling
function handleState(state: JARVISState): string {
switch (state.status) {
case 'idle':
return 'Ready'
case 'listening':
return `Listening for ${Date.now() - state.startTime}ms`
case 'processing':
return `Processing ${state.commandId}`
case 'responding':
return `${state.response} (${state.confidence}%)`
case 'error':
return `Error: ${state.error.message}`
default:
// ✅ Compile-time exhaustiveness check
const _exhaustive: never = state
return _exhaustive
}
}
// schemas/command.ts
import { z } from 'zod'
// ✅ Schema-first approach
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)
})
// ✅ Infer TypeScript type from schema
export type Command = z.infer<typeof commandSchema>
// ✅ Parse with full validation
export function parseCommand(data: unknown): Command {
return commandSchema.parse(data)
}
// ✅ Safe parse for error handling
export function tryParseCommand(data: unknown): Command | null {
const result = commandSchema.safeParse(data)
return result.success ? result.data : null
}
// ✅ Generic with constraints - ensures type safety for metrics
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 }
}
}
// ✅ Type predicate for safe narrowing
function isSuccessResponse<T>(
response: APIResponse<T>
): response is APIResponse<T> & { success: true; data: T } {
return response.success && response.data !== undefined
}
// Usage - type automatically narrowed
if (isSuccessResponse(response)) {
return response.data // ✅ Type is T, not T | undefined
}
// types/utilities.ts
// ✅ Deep readonly for immutable state
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K]
}
// ✅ Make specific keys required
type RequireKeys<T, K extends keyof T> = T & Required<Pick<T, K>>
// ✅ Extract event payloads
type EventPayload<T> = T extends { payload: infer P } ? P : never
// ✅ Async function return type
type AsyncReturnType<T extends (...args: any[]) => Promise<any>> =
T extends (...args: any[]) => Promise<infer R> ? R : never
// tests/utils/command-parser.test.ts
import { describe, it, expect } from 'vitest'
import { parseCommand } from '@/utils/command-parser'
describe('parseCommand', () => {
it('should parse valid command', () => {
expect(parseCommand('open settings')).toEqual({
action: 'open', target: 'settings', parameters: {}
})
})
it('should extract parameters', () => {
expect(parseCommand('set volume to 80')).toEqual({
action: 'set', target: 'volume', parameters: { value: 80 }
})
})
it('should throw on empty command', () => {
expect(() => parseCommand('')).toThrow('Command cannot be empty')
})
})
Write only code needed to make tests green.
Improve code quality while keeping tests green.
npx vitest run # Unit tests
npx eslint . --ext .ts,.tsx # Linting
npx tsc --noEmit # Type checking
// ❌ BAD - Recalculates on every render
const processed = data.map(item => heavyTransform(item))
// ✅ GOOD - Memoized computation
import { computed } from 'vue'
const processed = computed(() => data.value.map(item => heavyTransform(item)))
// ❌ BAD - Loads everything upfront
import { HeavyChart } from '@/components/HeavyChart'
// ✅ GOOD - Lazy load heavy components
import { defineAsyncComponent } from 'vue'
const HeavyChart = defineAsyncComponent(() => import('@/components/HeavyChart'))
// ❌ BAD - API call on every keystroke
const handleSearch = (q: string) => fetchResults(q)
// ✅ GOOD - Debounced search (300ms delay)
import { useDebounceFn } from '@vueuse/core'
const debouncedSearch = useDebounceFn((q: string) => fetchResults(q), 300)
// ❌ BAD - O(n) lookup
const user = users.find(u => u.id === id)
// ✅ GOOD - O(1) lookup with Map
const userMap = new Map(users.map(u => [u.id, u]))
const user = userMap.get(id)
// ✅ GOOD - O(1) membership check with Set
const allowed = new Set(['read', 'write'])
const hasAccess = allowed.has(permission)
// ❌ BAD - Sequential (total = sum of times)
const user = await fetchUser()
const metrics = await fetchMetrics()
// ✅ GOOD - Parallel (total = max of times)
const [user, metrics] = await Promise.all([fetchUser(), fetchMetrics()])
// ✅ GOOD - With error handling
const results = await Promise.allSettled([fetchUser(), fetchMetrics()])
TypeScript itself has a strong security record. Main risks come from:
| Risk Area | Description | Mitigation |
|---|---|---|
| Type Erasure | Types don't exist at runtime | Use Zod for external data validation |
| Any Type | Disables type checking | Enable noImplicitAny, use unknown |
| Type Assertions | Can bypass type system | Avoid as, use type guards instead |
| OWASP Category | TypeScript Mitigation |
|---|---|
| A03 Injection | Typed APIs prevent string interpolation in queries |
| A04 Insecure Design | Strong typing enforces secure interfaces |
| A08 Software Integrity | Compile-time checks catch errors before deployment |
// ❌ DANGEROUS - Type assertion bypasses safety
const userData = apiResponse as User
// ✅ SECURE - Runtime validation
const userData = userSchema.parse(apiResponse)
// ❌ DANGEROUS - any disables all checks
function process(data: any) { /* ... */ }
// ✅ SECURE - unknown requires narrowing
function process(data: unknown) {
const validated = commandSchema.parse(data)
// Now safely typed
}
// Type testing with vitest
import { expectTypeOf } from 'vitest'
describe('Type Safety', () => {
it('should enforce branded types', () => {
expectTypeOf(createUserId('usr_1234567890123456')).toEqualTypeOf<UserId>()
})
})
// Schema validation tests
describe('Command Schema', () => {
it('should reject invalid IDs', () => {
expect(() => commandSchema.parse({ id: 'invalid' })).toThrow()
})
it('should accept valid commands', () => {
const result = commandSchema.parse({ id: 'cmd_1234567890123456', action: 'query' })
expect(result.action).toBe('query')
})
})
// ❌ DANGEROUS - No runtime validation
const user = JSON.parse(data) as User
// ✅ SECURE - Validate at runtime
const user = userSchema.parse(JSON.parse(data))
// ❌ DANGEROUS - Runtime crash if undefined
function getConfig(key: string) {
return config[key].value // May be undefined!
}
// ✅ SECURE - Explicit null handling
function getConfig(key: string): string | undefined {
return config[key]?.value
}
// ❌ DANGEROUS - No type safety
const handlers: Record<string, Handler> = {}
handlers['cmd'].execute() // May be undefined!
// ✅ SECURE - Explicit lookup with check
const handler = handlers['cmd']
if (handler) {
handler.execute()
}
// ❌ BAD - Unreadable, slow compilation
type DeepPartialRecord<T> = T extends object
? { [K in keyof T]?: DeepPartialRecord<T[K]> }
: T extends Array<infer U>
? Array<DeepPartialRecord<U>>
: T
// ✅ GOOD - Simple, clear types
interface PartialConfig {
theme?: Partial<ThemeConfig>
metrics?: Partial<MetricsConfig>
}
strict: true enabled in tsconfignoUncheckedIndexedAccess: true enablednoImplicitAny: true enabledany types in production codenpx vitest run)npx eslint .)npx tsc --noEmit)TypeScript provides compile-time safety for JARVIS development:
unknown data with predicatesRemember : TypeScript only checks at compile time. Every boundary with external data must have runtime validation.
References :
references/advanced-patterns.md - Complex type patternsreferences/security-examples.md - Secure typing practicesWeekly Installs
79
Repository
GitHub Stars
32
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex60
gemini-cli60
opencode56
github-copilot56
cursor55
claude-code52
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
120,000 周安装
GrepAI Qdrant存储技能:高性能向量搜索,快速处理大型代码库
263 周安装
Browserbase Fetch API:快速获取网页内容、头部和元数据,无需浏览器会话
271 周安装
规划代理 (planning-agent) - AI驱动的软件开发实施规划工具,2025年最佳实践
265 周安装
区块链与Web3开发技能:智能合约、安全审计、DeFi协议实现与多链开发指南
258 周安装
Go gRPC生产环境配置指南:版本化Protobuf、TLS、健康检查与错误处理
261 周安装
Tinybird CLI 指南:本地开发、部署与数据操作完整教程
261 周安装