@mclawnet/agent 0.6.20 → 0.6.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/cli.js +63 -0
  2. package/dist/__tests__/checkpoint.test.d.ts +2 -0
  3. package/dist/__tests__/checkpoint.test.d.ts.map +1 -0
  4. package/dist/__tests__/fs-handler-decode.test.d.ts +2 -0
  5. package/dist/__tests__/fs-handler-decode.test.d.ts.map +1 -0
  6. package/dist/__tests__/idle-sweeper.test.d.ts +2 -0
  7. package/dist/__tests__/idle-sweeper.test.d.ts.map +1 -0
  8. package/dist/__tests__/mcp-config.test.d.ts +2 -0
  9. package/dist/__tests__/mcp-config.test.d.ts.map +1 -0
  10. package/dist/__tests__/schedule-runtime-spawn.test.d.ts +2 -0
  11. package/dist/__tests__/schedule-runtime-spawn.test.d.ts.map +1 -0
  12. package/dist/__tests__/schedule-runtime.test.d.ts +2 -0
  13. package/dist/__tests__/schedule-runtime.test.d.ts.map +1 -0
  14. package/dist/__tests__/session-limit.test.d.ts +2 -0
  15. package/dist/__tests__/session-limit.test.d.ts.map +1 -0
  16. package/dist/__tests__/swarm-cli-client.test.d.ts +2 -0
  17. package/dist/__tests__/swarm-cli-client.test.d.ts.map +1 -0
  18. package/dist/__tests__/swarm-control-dispatch.test.d.ts +2 -0
  19. package/dist/__tests__/swarm-control-dispatch.test.d.ts.map +1 -0
  20. package/dist/__tests__/swarm-session-bridge.test.d.ts +2 -0
  21. package/dist/__tests__/swarm-session-bridge.test.d.ts.map +1 -0
  22. package/dist/backend-adapter.d.ts +43 -0
  23. package/dist/backend-adapter.d.ts.map +1 -1
  24. package/dist/checkpoint.d.ts +67 -0
  25. package/dist/checkpoint.d.ts.map +1 -0
  26. package/dist/{chunk-RIK7IXSW.js → chunk-WJWCYGLQ.js} +1130 -147
  27. package/dist/chunk-WJWCYGLQ.js.map +1 -0
  28. package/dist/errors.d.ts +40 -0
  29. package/dist/errors.d.ts.map +1 -0
  30. package/dist/fs-handler.d.ts.map +1 -1
  31. package/dist/hub-connection.d.ts +13 -0
  32. package/dist/hub-connection.d.ts.map +1 -1
  33. package/dist/index.js +1 -1
  34. package/dist/schedule-runtime.d.ts +125 -0
  35. package/dist/schedule-runtime.d.ts.map +1 -0
  36. package/dist/session-manager.d.ts +102 -0
  37. package/dist/session-manager.d.ts.map +1 -1
  38. package/dist/skill-loader.d.ts +20 -0
  39. package/dist/skill-loader.d.ts.map +1 -1
  40. package/dist/start.d.ts +2 -0
  41. package/dist/start.d.ts.map +1 -1
  42. package/dist/start.js +1 -1
  43. package/dist/swarm-cli-client.d.ts +24 -0
  44. package/dist/swarm-cli-client.d.ts.map +1 -0
  45. package/dist/swarm-cli-client.js +83 -0
  46. package/dist/swarm-cli-client.js.map +1 -0
  47. package/dist/swarm-control-dispatch.d.ts +47 -0
  48. package/dist/swarm-control-dispatch.d.ts.map +1 -0
  49. package/dist/swarm-session-bridge.d.ts +22 -0
  50. package/dist/swarm-session-bridge.d.ts.map +1 -0
  51. package/package.json +6 -4
  52. package/skills/cocos-creator-3x-cn/SKILL.md +475 -0
  53. package/skills/cocos-creator-3x-cn/references/framework/asset-management.md +322 -0
  54. package/skills/cocos-creator-3x-cn/references/framework/component-system.md +348 -0
  55. package/skills/cocos-creator-3x-cn/references/framework/event-patterns.md +410 -0
  56. package/skills/cocos-creator-3x-cn/references/framework/playable-optimization.md +257 -0
  57. package/skills/cocos-creator-3x-cn/references/language/performance.md +363 -0
  58. package/skills/cocos-creator-3x-cn/references/language/quality-hygiene.md +307 -0
  59. package/skills/cocos-creator-3x-cn/references/review/architecture-review.md +183 -0
  60. package/skills/cocos-creator-3x-cn/references/review/quality-review.md +251 -0
  61. package/skills/cocos-performance-optimizer/SKILL.md +214 -0
  62. package/skills/game-development/2d-games/SKILL.md +129 -0
  63. package/skills/game-development/3d-games/SKILL.md +145 -0
  64. package/skills/game-development/SKILL.md +175 -0
  65. package/skills/game-development/game-art/SKILL.md +195 -0
  66. package/skills/game-development/game-audio/SKILL.md +200 -0
  67. package/skills/game-development/game-design/SKILL.md +139 -0
  68. package/skills/game-development/mobile-games/SKILL.md +118 -0
  69. package/skills/game-development/multiplayer/SKILL.md +142 -0
  70. package/skills/game-development/pc-games/SKILL.md +154 -0
  71. package/skills/game-development/vr-ar/SKILL.md +133 -0
  72. package/skills/game-development/web-games/SKILL.md +160 -0
  73. package/skills/game-engine/SKILL.md +140 -0
  74. package/skills/game-engine/assets/2d-maze-game.md +528 -0
  75. package/skills/game-engine/assets/2d-platform-game.md +1855 -0
  76. package/skills/game-engine/assets/gameBase-template-repo.md +310 -0
  77. package/skills/game-engine/assets/paddle-game-template.md +1528 -0
  78. package/skills/game-engine/assets/simple-2d-engine.md +507 -0
  79. package/skills/game-engine/references/3d-web-games.md +754 -0
  80. package/skills/game-engine/references/algorithms.md +843 -0
  81. package/skills/game-engine/references/basics.md +343 -0
  82. package/skills/game-engine/references/game-control-mechanisms.md +617 -0
  83. package/skills/game-engine/references/game-engine-core-principles.md +695 -0
  84. package/skills/game-engine/references/game-publishing.md +352 -0
  85. package/skills/game-engine/references/techniques.md +894 -0
  86. package/skills/game-engine/references/terminology.md +354 -0
  87. package/skills/game-engine/references/web-apis.md +1394 -0
  88. package/skills/theone-cocos-standards/SKILL.md +557 -0
  89. package/skills/theone-cocos-standards/references/framework/component-system.md +645 -0
  90. package/skills/theone-cocos-standards/references/framework/event-patterns.md +433 -0
  91. package/skills/theone-cocos-standards/references/framework/playable-optimization.md +429 -0
  92. package/skills/theone-cocos-standards/references/framework/size-optimization.md +308 -0
  93. package/skills/theone-cocos-standards/references/language/modern-typescript.md +658 -0
  94. package/skills/theone-cocos-standards/references/language/performance.md +580 -0
  95. package/skills/theone-cocos-standards/references/language/quality-hygiene.md +582 -0
  96. package/skills/theone-cocos-standards/references/review/architecture-review.md +250 -0
  97. package/skills/theone-cocos-standards/references/review/performance-review.md +288 -0
  98. package/skills/theone-cocos-standards/references/review/quality-review.md +239 -0
  99. package/dist/chunk-RIK7IXSW.js.map +0 -1
@@ -0,0 +1,658 @@
1
+ # Modern TypeScript Patterns
2
+
3
+ ## Array Methods Over Loops
4
+
5
+ ```typescript
6
+ import { _decorator, Component, Node } from 'cc';
7
+ const { ccclass } = _decorator;
8
+
9
+ interface Enemy {
10
+ node: Node;
11
+ isActive: boolean;
12
+ health: number;
13
+ damage: number;
14
+ }
15
+
16
+ @ccclass('EnemyManager')
17
+ export class EnemyManager extends Component {
18
+ private readonly enemies: Enemy[] = [];
19
+
20
+ // ✅ EXCELLENT: Array methods for filtering
21
+ public getActiveEnemies(): Enemy[] {
22
+ return this.enemies.filter(enemy => enemy.isActive);
23
+ }
24
+
25
+ // ✅ EXCELLENT: Array methods for mapping
26
+ public getEnemyPositions(): Vec3[] {
27
+ return this.enemies.map(enemy => enemy.node.position.clone());
28
+ }
29
+
30
+ // ✅ EXCELLENT: Array methods for reduction
31
+ public getTotalDamage(): number {
32
+ return this.enemies.reduce((total, enemy) => total + enemy.damage, 0);
33
+ }
34
+
35
+ // ✅ EXCELLENT: Chaining array methods
36
+ public getActiveEnemyDamage(): number {
37
+ return this.enemies
38
+ .filter(enemy => enemy.isActive)
39
+ .reduce((total, enemy) => total + enemy.damage, 0);
40
+ }
41
+
42
+ // ✅ EXCELLENT: find instead of manual loop
43
+ public findEnemyById(id: string): Enemy | undefined {
44
+ return this.enemies.find(enemy => enemy.node.uuid === id);
45
+ }
46
+
47
+ // ✅ EXCELLENT: some/every for existence checks
48
+ public hasActiveEnemies(): boolean {
49
+ return this.enemies.some(enemy => enemy.isActive);
50
+ }
51
+
52
+ public areAllEnemiesDead(): boolean {
53
+ return this.enemies.every(enemy => enemy.health <= 0);
54
+ }
55
+ }
56
+
57
+ // ❌ BAD: Manual loops
58
+ public getActiveEnemies(): Enemy[] {
59
+ const active: Enemy[] = [];
60
+ for (let i = 0; i < this.enemies.length; i++) {
61
+ if (this.enemies[i].isActive) {
62
+ active.push(this.enemies[i]);
63
+ }
64
+ }
65
+ return active;
66
+ }
67
+
68
+ // ❌ BAD: Manual accumulation
69
+ public getTotalDamage(): number {
70
+ let total = 0;
71
+ for (const enemy of this.enemies) {
72
+ total += enemy.damage;
73
+ }
74
+ return total;
75
+ }
76
+ ```
77
+
78
+ ## Arrow Functions and Callbacks
79
+
80
+ ```typescript
81
+ import { _decorator, Component, Node, EventTouch } from 'cc';
82
+ const { ccclass } = _decorator;
83
+
84
+ @ccclass('InputHandler')
85
+ export class InputHandler extends Component {
86
+ private readonly buttons: Node[] = [];
87
+
88
+ // ✅ EXCELLENT: Arrow functions for callbacks
89
+ protected onEnable(): void {
90
+ this.buttons.forEach(button => {
91
+ button.on(Node.EventType.TOUCH_START, this.onButtonClick, this);
92
+ });
93
+ }
94
+
95
+ protected onDisable(): void {
96
+ this.buttons.forEach(button => {
97
+ button.off(Node.EventType.TOUCH_START, this.onButtonClick, this);
98
+ });
99
+ }
100
+
101
+ // ✅ GOOD: Arrow function preserves this context
102
+ private readonly onButtonClick = (event: EventTouch): void => {
103
+ const button = event.target as Node;
104
+ this.handleButtonClick(button);
105
+ };
106
+
107
+ // ✅ GOOD: Arrow function for event handling
108
+ private setupAsyncOperation(): void {
109
+ setTimeout(() => {
110
+ this.processData();
111
+ }, 1000);
112
+ }
113
+
114
+ // ✅ GOOD: Arrow function in Promise chains
115
+ private async loadData(): Promise<void> {
116
+ fetch('data.json')
117
+ .then(response => response.json())
118
+ .then(data => this.processData(data))
119
+ .catch(error => this.handleError(error));
120
+ }
121
+ }
122
+
123
+ // ❌ BAD: Function expression loses this context
124
+ protected onEnable(): void {
125
+ this.buttons.forEach(function(button) {
126
+ // 'this' is undefined or wrong context
127
+ button.on(Node.EventType.TOUCH_START, this.onButtonClick, this);
128
+ });
129
+ }
130
+
131
+ // ❌ BAD: Verbose function syntax
132
+ private setupAsyncOperation(): void {
133
+ const self = this;
134
+ setTimeout(function() {
135
+ self.processData();
136
+ }, 1000);
137
+ }
138
+ ```
139
+
140
+ ## Destructuring
141
+
142
+ ```typescript
143
+ import { _decorator, Component, Node, Vec3 } from 'cc';
144
+ const { ccclass, property } = _decorator;
145
+
146
+ interface PlayerData {
147
+ id: string;
148
+ name: string;
149
+ level: number;
150
+ health: number;
151
+ position: { x: number; y: number; z: number };
152
+ }
153
+
154
+ @ccclass('PlayerController')
155
+ export class PlayerController extends Component {
156
+ // ✅ EXCELLENT: Destructuring in parameters
157
+ public updatePlayer({ id, name, level, health, position }: PlayerData): void {
158
+ console.log(`Updating ${name} (${id}) at level ${level}`);
159
+
160
+ // ✅ EXCELLENT: Nested destructuring
161
+ const { x, y, z } = position;
162
+ this.node.setPosition(x, y, z);
163
+ }
164
+
165
+ // ✅ EXCELLENT: Destructuring with defaults
166
+ public loadConfig({ speed = 100, jumpHeight = 50, maxHealth = 100 } = {}): void {
167
+ this.speed = speed;
168
+ this.jumpHeight = jumpHeight;
169
+ this.maxHealth = maxHealth;
170
+ }
171
+
172
+ // ✅ EXCELLENT: Array destructuring
173
+ public getPlayerPosition(): Vec3 {
174
+ const [x, y, z] = [this.node.position.x, this.node.position.y, this.node.position.z];
175
+ return new Vec3(x, y, z);
176
+ }
177
+
178
+ // ✅ EXCELLENT: Rest operator with destructuring
179
+ public handleInput({ type, ...eventData }: InputEvent): void {
180
+ switch (type) {
181
+ case 'touch':
182
+ this.handleTouch(eventData);
183
+ break;
184
+ case 'key':
185
+ this.handleKey(eventData);
186
+ break;
187
+ }
188
+ }
189
+ }
190
+
191
+ // ❌ BAD: No destructuring
192
+ public updatePlayer(playerData: PlayerData): void {
193
+ console.log(`Updating ${playerData.name} (${playerData.id}) at level ${playerData.level}`);
194
+ this.node.setPosition(playerData.position.x, playerData.position.y, playerData.position.z);
195
+ }
196
+
197
+ // ❌ BAD: Verbose property access
198
+ public loadConfig(config: Config): void {
199
+ this.speed = config.speed !== undefined ? config.speed : 100;
200
+ this.jumpHeight = config.jumpHeight !== undefined ? config.jumpHeight : 50;
201
+ this.maxHealth = config.maxHealth !== undefined ? config.maxHealth : 100;
202
+ }
203
+ ```
204
+
205
+ ## Spread Operator
206
+
207
+ ```typescript
208
+ import { _decorator, Component } from 'cc';
209
+ const { ccclass } = _decorator;
210
+
211
+ interface GameConfig {
212
+ playerName: string;
213
+ difficulty: string;
214
+ soundEnabled: boolean;
215
+ }
216
+
217
+ @ccclass('GameManager')
218
+ export class GameManager extends Component {
219
+ private readonly defaultConfig: GameConfig = {
220
+ playerName: 'Player',
221
+ difficulty: 'normal',
222
+ soundEnabled: true,
223
+ };
224
+
225
+ // ✅ EXCELLENT: Spread for object merging
226
+ public createConfig(overrides: Partial<GameConfig>): GameConfig {
227
+ return { ...this.defaultConfig, ...overrides };
228
+ }
229
+
230
+ // ✅ EXCELLENT: Spread for array concatenation
231
+ private readonly baseEnemies: string[] = ['goblin', 'orc'];
232
+ private readonly bossEnemies: string[] = ['dragon', 'demon'];
233
+
234
+ public getAllEnemies(): string[] {
235
+ return [...this.baseEnemies, ...this.bossEnemies];
236
+ }
237
+
238
+ // ✅ EXCELLENT: Spread for array cloning
239
+ public cloneEnemyList(): string[] {
240
+ return [...this.baseEnemies];
241
+ }
242
+
243
+ // ✅ EXCELLENT: Spread in function calls
244
+ public calculateMaxValue(...values: number[]): number {
245
+ return Math.max(...values);
246
+ }
247
+
248
+ // ✅ EXCELLENT: Spread for immutable updates
249
+ public addEnemy(enemy: string): void {
250
+ this.baseEnemies = [...this.baseEnemies, enemy];
251
+ }
252
+ }
253
+
254
+ // ❌ BAD: Manual merging
255
+ public createConfig(overrides: Partial<GameConfig>): GameConfig {
256
+ const config: GameConfig = {
257
+ playerName: overrides.playerName ?? this.defaultConfig.playerName,
258
+ difficulty: overrides.difficulty ?? this.defaultConfig.difficulty,
259
+ soundEnabled: overrides.soundEnabled ?? this.defaultConfig.soundEnabled,
260
+ };
261
+ return config;
262
+ }
263
+
264
+ // ❌ BAD: Manual concatenation
265
+ public getAllEnemies(): string[] {
266
+ const enemies: string[] = [];
267
+ for (const enemy of this.baseEnemies) {
268
+ enemies.push(enemy);
269
+ }
270
+ for (const enemy of this.bossEnemies) {
271
+ enemies.push(enemy);
272
+ }
273
+ return enemies;
274
+ }
275
+ ```
276
+
277
+ ## Optional Chaining (?.)
278
+
279
+ ```typescript
280
+ import { _decorator, Component, Node } from 'cc';
281
+ const { ccclass, property } = _decorator;
282
+
283
+ interface Player {
284
+ name: string;
285
+ stats?: {
286
+ health?: number;
287
+ level?: number;
288
+ };
289
+ inventory?: {
290
+ items?: Item[];
291
+ };
292
+ }
293
+
294
+ @ccclass('PlayerManager')
295
+ export class PlayerManager extends Component {
296
+ @property(Node)
297
+ private readonly playerNode: Node | null = null;
298
+
299
+ // ✅ EXCELLENT: Optional chaining for safe access
300
+ public getPlayerName(): string | undefined {
301
+ return this.playerNode?.name;
302
+ }
303
+
304
+ // ✅ EXCELLENT: Deep optional chaining
305
+ public getPlayerHealth(player: Player): number | undefined {
306
+ return player?.stats?.health;
307
+ }
308
+
309
+ // ✅ EXCELLENT: Optional chaining with arrays
310
+ public getFirstItem(player: Player): Item | undefined {
311
+ return player?.inventory?.items?.[0];
312
+ }
313
+
314
+ // ✅ EXCELLENT: Optional chaining with methods
315
+ public getComponentName(): string | undefined {
316
+ return this.playerNode?.getComponent(PlayerController)?.getName?.();
317
+ }
318
+
319
+ // ✅ EXCELLENT: Combining with nullish coalescing
320
+ public getDisplayName(): string {
321
+ return this.playerNode?.name ?? 'Unknown Player';
322
+ }
323
+ }
324
+
325
+ // ❌ BAD: Manual null checking
326
+ public getPlayerName(): string | undefined {
327
+ if (this.playerNode !== null && this.playerNode !== undefined) {
328
+ return this.playerNode.name;
329
+ }
330
+ return undefined;
331
+ }
332
+
333
+ // ❌ BAD: Nested null checks
334
+ public getPlayerHealth(player: Player): number | undefined {
335
+ if (player) {
336
+ if (player.stats) {
337
+ if (player.stats.health !== undefined) {
338
+ return player.stats.health;
339
+ }
340
+ }
341
+ }
342
+ return undefined;
343
+ }
344
+ ```
345
+
346
+ ## Nullish Coalescing (??)
347
+
348
+ ```typescript
349
+ import { _decorator, Component } from 'cc';
350
+ const { ccclass } = _decorator;
351
+
352
+ interface GameConfig {
353
+ playerName?: string;
354
+ maxHealth?: number;
355
+ soundVolume?: number;
356
+ enableTutorial?: boolean;
357
+ }
358
+
359
+ @ccclass('ConfigManager')
360
+ export class ConfigManager extends Component {
361
+ // ✅ EXCELLENT: Nullish coalescing for defaults
362
+ public loadConfig(config: GameConfig): void {
363
+ const playerName = config.playerName ?? 'Player';
364
+ const maxHealth = config.maxHealth ?? 100;
365
+ const soundVolume = config.soundVolume ?? 0.5;
366
+ const enableTutorial = config.enableTutorial ?? true;
367
+
368
+ console.log({ playerName, maxHealth, soundVolume, enableTutorial });
369
+ }
370
+
371
+ // ✅ EXCELLENT: Nullish coalescing preserves falsy values
372
+ public getVolume(volume?: number): number {
373
+ // Returns 0 if volume is 0 (not using || which would return 1)
374
+ return volume ?? 1;
375
+ }
376
+
377
+ // ✅ EXCELLENT: Chaining nullish coalescing
378
+ public getPlayerName(primaryName?: string, secondaryName?: string): string {
379
+ return primaryName ?? secondaryName ?? 'Unknown';
380
+ }
381
+
382
+ // ✅ EXCELLENT: Nullish coalescing with optional chaining
383
+ public getHealthDisplay(player?: Player): string {
384
+ const health = player?.stats?.health ?? 0;
385
+ return `Health: ${health}`;
386
+ }
387
+ }
388
+
389
+ // ❌ BAD: Using || operator (treats 0, '', false as null)
390
+ public getVolume(volume?: number): number {
391
+ return volume || 1; // Returns 1 even if volume is 0
392
+ }
393
+
394
+ // ❌ BAD: Manual null/undefined checks
395
+ public loadConfig(config: GameConfig): void {
396
+ const playerName = config.playerName !== null && config.playerName !== undefined
397
+ ? config.playerName
398
+ : 'Player';
399
+ }
400
+
401
+ // ❌ BAD: Verbose ternary
402
+ public getPlayerName(name?: string): string {
403
+ return name !== undefined && name !== null ? name : 'Unknown';
404
+ }
405
+ ```
406
+
407
+ ## Type Guards
408
+
409
+ ```typescript
410
+ import { _decorator, Component, Node } from 'cc';
411
+ const { ccclass } = _decorator;
412
+
413
+ // ✅ EXCELLENT: Type guard for interface
414
+ interface Player {
415
+ type: 'player';
416
+ health: number;
417
+ level: number;
418
+ }
419
+
420
+ interface Enemy {
421
+ type: 'enemy';
422
+ health: number;
423
+ damage: number;
424
+ }
425
+
426
+ type Entity = Player | Enemy;
427
+
428
+ function isPlayer(entity: Entity): entity is Player {
429
+ return entity.type === 'player';
430
+ }
431
+
432
+ function isEnemy(entity: Entity): entity is Enemy {
433
+ return entity.type === 'enemy';
434
+ }
435
+
436
+ @ccclass('CombatManager')
437
+ export class CombatManager extends Component {
438
+ public handleEntity(entity: Entity): void {
439
+ if (isPlayer(entity)) {
440
+ // TypeScript knows entity is Player
441
+ console.log(`Player level: ${entity.level}`);
442
+ } else if (isEnemy(entity)) {
443
+ // TypeScript knows entity is Enemy
444
+ console.log(`Enemy damage: ${entity.damage}`);
445
+ }
446
+ }
447
+
448
+ // ✅ EXCELLENT: Type guard for null/undefined
449
+ private isValidNode(node: Node | null | undefined): node is Node {
450
+ return node !== null && node !== undefined;
451
+ }
452
+
453
+ public processNode(node: Node | null): void {
454
+ if (this.isValidNode(node)) {
455
+ // TypeScript knows node is Node (not null)
456
+ node.setPosition(0, 0, 0);
457
+ }
458
+ }
459
+
460
+ // ✅ EXCELLENT: Type guard for component
461
+ private hasPlayerController(node: Node): node is Node & { getComponent(PlayerController): PlayerController } {
462
+ return node.getComponent(PlayerController) !== null;
463
+ }
464
+
465
+ public updatePlayer(node: Node): void {
466
+ if (this.hasPlayerController(node)) {
467
+ // TypeScript knows component exists
468
+ const controller = node.getComponent(PlayerController)!;
469
+ controller.update();
470
+ }
471
+ }
472
+ }
473
+
474
+ // ❌ BAD: No type guards, type assertions everywhere
475
+ public handleEntity(entity: Entity): void {
476
+ if (entity.type === 'player') {
477
+ console.log(`Player level: ${(entity as Player).level}`); // Type assertion
478
+ } else {
479
+ console.log(`Enemy damage: ${(entity as Enemy).damage}`); // Type assertion
480
+ }
481
+ }
482
+ ```
483
+
484
+ ## Utility Types
485
+
486
+ ```typescript
487
+ import { _decorator, Component } from 'cc';
488
+ const { ccclass } = _decorator;
489
+
490
+ interface GameConfig {
491
+ playerName: string;
492
+ maxHealth: number;
493
+ difficulty: string;
494
+ soundEnabled: boolean;
495
+ }
496
+
497
+ @ccclass('ConfigManager')
498
+ export class ConfigManager extends Component {
499
+ // ✅ EXCELLENT: Partial for optional properties
500
+ public updateConfig(updates: Partial<GameConfig>): void {
501
+ // All properties are optional
502
+ }
503
+
504
+ // ✅ EXCELLENT: Required for mandatory properties
505
+ public validateConfig(config: Required<GameConfig>): void {
506
+ // All properties are required
507
+ }
508
+
509
+ // ✅ EXCELLENT: Readonly for immutable objects
510
+ private readonly defaultConfig: Readonly<GameConfig> = {
511
+ playerName: 'Player',
512
+ maxHealth: 100,
513
+ difficulty: 'normal',
514
+ soundEnabled: true,
515
+ };
516
+
517
+ // ✅ EXCELLENT: Pick for selecting properties
518
+ public getDisplayInfo(config: GameConfig): Pick<GameConfig, 'playerName' | 'difficulty'> {
519
+ return {
520
+ playerName: config.playerName,
521
+ difficulty: config.difficulty,
522
+ };
523
+ }
524
+
525
+ // ✅ EXCELLENT: Omit for excluding properties
526
+ public getPublicConfig(config: GameConfig): Omit<GameConfig, 'soundEnabled'> {
527
+ const { soundEnabled, ...publicConfig } = config;
528
+ return publicConfig;
529
+ }
530
+
531
+ // ✅ EXCELLENT: Record for key-value mappings
532
+ private readonly difficultyMultipliers: Record<string, number> = {
533
+ easy: 0.5,
534
+ normal: 1.0,
535
+ hard: 1.5,
536
+ expert: 2.0,
537
+ };
538
+
539
+ // ✅ EXCELLENT: ReturnType for function return types
540
+ private createPlayer(): { name: string; level: number } {
541
+ return { name: 'Player', level: 1 };
542
+ }
543
+
544
+ type PlayerType = ReturnType<typeof this.createPlayer>;
545
+ }
546
+ ```
547
+
548
+ ## Async/Await Patterns
549
+
550
+ ```typescript
551
+ import { _decorator, Component } from 'cc';
552
+ const { ccclass } = _decorator;
553
+
554
+ @ccclass('DataManager')
555
+ export class DataManager extends Component {
556
+ // ✅ EXCELLENT: Async/await for sequential operations
557
+ public async loadGameData(): Promise<void> {
558
+ try {
559
+ const playerData = await this.fetchPlayerData();
560
+ const levelData = await this.fetchLevelData(playerData.currentLevel);
561
+ await this.initializeGame(playerData, levelData);
562
+ } catch (error) {
563
+ console.error('Failed to load game data:', error);
564
+ throw error;
565
+ }
566
+ }
567
+
568
+ // ✅ EXCELLENT: Promise.all for parallel operations
569
+ public async loadAllData(): Promise<void> {
570
+ try {
571
+ const [playerData, configData, assetsData] = await Promise.all([
572
+ this.fetchPlayerData(),
573
+ this.fetchConfigData(),
574
+ this.fetchAssetsData(),
575
+ ]);
576
+
577
+ this.initializeWithData(playerData, configData, assetsData);
578
+ } catch (error) {
579
+ console.error('Failed to load data:', error);
580
+ throw error;
581
+ }
582
+ }
583
+
584
+ // ✅ EXCELLENT: Promise.allSettled for partial failures
585
+ public async loadDataWithFallback(): Promise<void> {
586
+ const results = await Promise.allSettled([
587
+ this.fetchPlayerData(),
588
+ this.fetchConfigData(),
589
+ this.fetchAssetsData(),
590
+ ]);
591
+
592
+ results.forEach((result, index) => {
593
+ if (result.status === 'fulfilled') {
594
+ console.log(`Data ${index} loaded:`, result.value);
595
+ } else {
596
+ console.error(`Data ${index} failed:`, result.reason);
597
+ }
598
+ });
599
+ }
600
+
601
+ // ✅ EXCELLENT: Error handling with async/await
602
+ public async savePlayerData(data: PlayerData): Promise<boolean> {
603
+ try {
604
+ await this.validateData(data);
605
+ await this.uploadData(data);
606
+ return true;
607
+ } catch (error) {
608
+ if (error instanceof ValidationError) {
609
+ console.error('Invalid data:', error.message);
610
+ } else if (error instanceof NetworkError) {
611
+ console.error('Network error:', error.message);
612
+ } else {
613
+ console.error('Unknown error:', error);
614
+ }
615
+ return false;
616
+ }
617
+ }
618
+
619
+ private async fetchPlayerData(): Promise<PlayerData> {
620
+ // Implementation
621
+ }
622
+
623
+ private async fetchLevelData(level: number): Promise<LevelData> {
624
+ // Implementation
625
+ }
626
+ }
627
+
628
+ // ❌ BAD: Promise chains (callback hell)
629
+ public loadGameData(): void {
630
+ this.fetchPlayerData()
631
+ .then(playerData => {
632
+ return this.fetchLevelData(playerData.currentLevel);
633
+ })
634
+ .then(levelData => {
635
+ return this.initializeGame(playerData, levelData); // playerData not in scope!
636
+ })
637
+ .catch(error => {
638
+ console.error('Failed:', error);
639
+ });
640
+ }
641
+ ```
642
+
643
+ ## Summary: Modern TypeScript Checklist
644
+
645
+ **Use these patterns for cleaner, more maintainable code:**
646
+
647
+ - [ ] Array methods (map/filter/reduce) instead of manual loops
648
+ - [ ] Arrow functions for callbacks and event handlers
649
+ - [ ] Destructuring for cleaner parameter handling
650
+ - [ ] Spread operator for object/array operations
651
+ - [ ] Optional chaining (?.) for safe property access
652
+ - [ ] Nullish coalescing (??) for default values
653
+ - [ ] Type guards for type-safe narrowing
654
+ - [ ] Utility types (Partial, Required, Readonly, Pick, Omit, Record)
655
+ - [ ] Async/await for asynchronous operations
656
+ - [ ] Promise.all/allSettled for parallel operations
657
+
658
+ **Modern TypeScript makes code more concise, readable, and type-safe.**