# 强类型命令系统

## 概述

强类型命令系统通过从 C# 模型自动生成 TypeScript 类型定义，实现端到端的类型安全。该系统提供编译时类型检查、智能提示和运行时验证，同时保持向后兼容性。

## 架构设计

### 分层架构

```
C# 模型定义 → TypeScript 类型生成 → WebSocket 协议集成
```

- **C# 模型层**：定义命令的业务逻辑和数据结构
- **类型生成层**：自动将 C# 类型转换为 TypeScript 定义
- **协议集成层**：将强类型集成到 WebSocket 协议中

### 核心组件

1. **命令类型定义** (`command-types.ts`)
   - 所有强类型命令的 TypeScript 接口
   - 命令代码到类型的映射
   - 类型守卫函数

2. **命令工厂** (`command-factory.ts`)
   - 类型安全的命令创建函数
   - 参数验证和默认值处理
   - 通用工厂方法

3. **类型验证器** (`CommandTypeValidator`)
   - 运行时类型验证
   - 详细的错误报告
   - 可扩展的验证规则

## 使用方法

### 1. 基础使用

```typescript
import { 
  createLedSwitchCommand, 
  createBlockPlayCommand,
  Priority 
} from '@jrsoft/subway-protocol';

// 创建 LED 开关命令
const ledCommand = createLedSwitchCommand(
  'led-req-001',      // requestRef
  'td-01',            // targetClientId (设备ID)  
  15,                 // deviceId (子硬件ID)
  'ON',               // switch state
  'write',            // operation type
  {
    priority: Priority.HIGH,
    timeout: 5000,
    callback: 'http://backend/api/callback'
  }
);

// 创建区块播放命令
const playCommand = createBlockPlayCommand(
  'play-req-002',
  'td-01',            // targetClientId (设备ID)
  15,                 // deviceId (子硬件ID)
  3,                  // blockNumber
  'loop',             // playMode
  'write',
  { priority: Priority.NORMAL }
);
```

### 2. 类型安全的优势

```typescript
// ✅ 强类型：编译时类型检查
const command = createLedSwitchCommand(
  'req-123',
  'td-01', 
  42,
  'ON'  // 只能是 'ON' | 'OFF'
);

// ❌ 编译错误：类型不匹配
const badCommand = createLedSwitchCommand(
  'req-123',
  'td-01',
  42,
  'INVALID'  // Error: Argument of type '"INVALID"' is not assignable
);

// IDE 智能提示
command.parameters.switch // 自动提示: 'ON' | 'OFF'
command.deviceType        // 自动提示: 'pillar'
command.operationType     // 自动提示: 'read' | 'write'
```

### 3. 运行时验证

```typescript
import { CommandTypeValidator } from '@jrsoft/subway-protocol';

// 验证命令
const validation = CommandTypeValidator.validateCommand(command);
if (!validation.valid) {
  console.error('Command validation failed:', validation.errors);
}

// 验证特定命令类型
if (CommandTypeValidator.isLedSwitchCommand(command)) {
  // TypeScript 知道这是 LedSwitchCommand
  console.log(command.parameters.switch); // 'ON' | 'OFF'
}
```

### 4. 批量命令支持

```typescript
import { createBatchCommand } from '@jrsoft/subway-protocol';

// 创建批量 LED 控制命令
const batchLedCommand = createBatchCommand(
  'batch-req-001',
  {
    commandCode: 'LedSwitch',
    deviceType: 'pillar',
    operationType: 'write',
    parameters: {
      switch: 'ON',
      targets: '1-10,30-40',  // 批量目标
      batch: true
    }
  },
  {
    priority: Priority.HIGH,
    timeout: 30000
  }
);
```

### 5. 泛型工厂方法

```typescript
import { 
  TypedCommandFactory,
  CommandTypeMap 
} from '@jrsoft/subway-protocol';

// 使用泛型工厂创建任意类型的命令
const typedCommand = TypedCommandFactory.createTypedCommandMessage(
  'generic-req-003',
  'device-01',
  'BlockPlay',  // 命令代码作为类型参数
  {
    blockNumber: 5,
    playMode: 'sequence'
  },
  { priority: Priority.LOW }
);

// TypeScript 自动推断返回类型为 CommandMessage<BlockPlayCommand>
```

## 支持的命令类型

此处省略

完整的命令列表请参考 [API 文档](../06-reference/api.md)。

## 与通用命令的互操作

### 向后兼容

```typescript
// 强类型命令仍然是标准的 Command
export type Command = SpecificCommand | GenericCommand;

// 可以混合使用
const commands: Command[] = [
  createLedSwitchCommand(...),  // 强类型
  {                             // 通用类型
    commandCode: 'CUSTOM_COMMAND',
    deviceType: 'custom',
    operationType: 'write',
    parameters: { customParam: 'value' }
  }
];
```

### 类型转换

```typescript
import { CommandTypeConverter } from '@jrsoft/subway-protocol';

// 将通用命令转换为强类型（如果可能）
const genericCommand = {
  commandCode: 'LedSwitch',
  parameters: { switch: 'ON' }
};

const specificCommand = CommandTypeConverter.toSpecificCommand(genericCommand);
if (specificCommand && CommandTypeValidator.isLedSwitchCommand(specificCommand)) {
  // 现在有完整的类型信息
}
```

## 最佳实践

### 1. 优先使用强类型

```typescript
// ✅ 推荐：使用强类型命令工厂
const command = createLedSwitchCommand(...);

// ❌ 避免：手动构造命令对象
const command = {
  commandCode: 'LedSwitch',
  parameters: { switch: 'ON' }
};
```

### 2. 统一错误处理

```typescript
try {
  const command = createLedSwitchCommand(...);
  const validation = CommandTypeValidator.validateCommand(command);
  
  if (!validation.valid) {
    throw new Error(`Invalid command: ${validation.errors.join(', ')}`);
  }
  
  // 发送命令
} catch (error) {
  console.error('Command creation failed:', error);
}
```

### 3. 类型守卫的使用

```typescript
function handleCommand(command: Command) {
  if (CommandTypeValidator.isLedSwitchCommand(command)) {
    // 处理 LED 开关命令
    console.log(`Switching LED to ${command.parameters.switch}`);
  } else if (CommandTypeValidator.isBlockPlayCommand(command)) {
    // 处理区块播放命令
    console.log(`Playing block ${command.parameters.blockNumber}`);
  } else {
    // 处理通用命令
    console.log(`Generic command: ${command.commandCode}`);
  }
}
```

### 4. 扩展自定义命令

```typescript
// 定义自定义命令接口
interface CustomCommand extends BaseSpecificCommand {
  commandCode: 'CustomCommand';
  parameters: {
    customField: string;
    customValue: number;
  };
}

// 添加到命令映射
declare module '@jrsoft/subway-protocol' {
  interface CommandTypeMap {
    CustomCommand: CustomCommand;
  }
}

// 创建自定义工厂函数
export function createCustomCommand(
  requestRef: string,
  targetClientId: string,
  customField: string,
  customValue: number,
  options?: CommandOptions
): CommandMessage<CustomCommand> {
  return TypedCommandFactory.createTypedCommandMessage(
    requestRef,
    targetClientId,
    'CustomCommand',
    { customField, customValue },
    options
  );
}
```

## 工具支持

### TypeScript 配置

```json
{
  "compilerOptions": {
    "strict": true,
    "strictNullChecks": true,
    "noImplicitAny": true
  }
}
```

### ESLint 规则

```json
{
  "rules": {
    "@typescript-eslint/no-explicit-any": "Uerror",
    "@typescript-eslint/explicit-function-return-type": "warn"
  }
}
```

## 迁移指南

### 从通用命令迁移到强类型

1. **识别使用的命令代码**
   ```typescript
   // 旧代码
   const command = {
     commandCode: 'LedSwitch',
     parameters: { switch: 'ON' }
   };
   ```

2. **使用对应的工厂函数**
   ```typescript
   // 新代码
   const command = createLedSwitchCommand(
     requestRef,
     targetClientId,
     deviceId,
     'ON',
     'write'
   );
   ```

3. **更新类型注解**
   ```typescript
   // 旧代码
   function handleCommand(command: any) { }
   
   // 新代码
   function handleCommand(command: LedSwitchCommand) { }
   ```

## 总结

强类型命令系统提供了：

1. **编译时安全** - 在开发阶段捕获类型错误
2. **更好的开发体验** - IDE 智能提示和自动补全
3. **运行时验证** - 确保数据完整性
4. **向后兼容** - 可以渐进式迁移
5. **可扩展性** - 轻松添加新的命令类型

这种设计既保证了类型安全，又保持了系统的灵活性，是现代 TypeScript 应用的最佳实践。