feat(types): 添加类型检查脚本和迁移指南

添加 check-types.ps1 脚本用于检查项目各模块的类型定义
添加 migrate-types.ps1 脚本用于自动迁移类型导入路径
添加类型迁移指南文档说明迁移步骤和最佳实践
添加共享类型测试用例验证 schema 定义
This commit is contained in:
2026-03-20 18:00:31 +08:00
parent 427becbc8f
commit 888d3844f3
4 changed files with 837 additions and 0 deletions

View File

@@ -0,0 +1,247 @@
import { describe, it, expect } from 'vitest';
import { z } from 'zod';
import {
UserSchema,
UserRoleSchema,
UserStatusSchema,
CreateUserSchema,
UpdateUserSchema
} from '@shared/schemas/user.schema';
import {
ProductSchema,
ProductStatusSchema
} from '@shared/schemas/product.schema';
import {
OrderSchema,
OrderStatusSchema
} from '@shared/schemas/order.schema';
import {
BaseMessageSchema,
MessageTypeSchema,
MessageResponseSchema
} from '@shared/schemas/message.schema';
describe('User Schema', () => {
it('should validate valid user data', () => {
const validUser = {
id: '123',
name: 'John Doe',
email: 'john@example.com',
role: 'admin',
status: 'active',
createdAt: new Date(),
updatedAt: new Date()
};
const result = UserSchema.safeParse(validUser);
expect(result.success).toBe(true);
});
it('should reject invalid email', () => {
const invalidUser = {
id: '123',
name: 'John Doe',
email: 'invalid-email',
role: 'admin',
status: 'active',
createdAt: new Date(),
updatedAt: new Date()
};
const result = UserSchema.safeParse(invalidUser);
expect(result.success).toBe(false);
});
it('should reject invalid role', () => {
const invalidUser = {
id: '123',
name: 'John Doe',
email: 'john@example.com',
role: 'invalid_role',
status: 'active',
createdAt: new Date(),
updatedAt: new Date()
};
const result = UserSchema.safeParse(invalidUser);
expect(result.success).toBe(false);
});
});
describe('Product Schema', () => {
it('should validate valid product data', () => {
const validProduct = {
id: '123',
name: 'Test Product',
sku: 'SKU-001',
price: 99.99,
stock: 100,
status: 'active',
createdAt: new Date(),
updatedAt: new Date()
};
const result = ProductSchema.safeParse(validProduct);
expect(result.success).toBe(true);
});
it('should reject negative price', () => {
const invalidProduct = {
id: '123',
name: 'Test Product',
sku: 'SKU-001',
price: -10,
stock: 100,
status: 'active',
createdAt: new Date(),
updatedAt: new Date()
};
const result = ProductSchema.safeParse(invalidProduct);
expect(result.success).toBe(false);
});
});
describe('Order Schema', () => {
it('should validate valid order data', () => {
const validOrder = {
id: '123',
orderNumber: 'ORD-001',
status: 'pending',
items: [
{
productId: 'p1',
productName: 'Product 1',
quantity: 2,
unitPrice: 50,
totalPrice: 100
}
],
totalAmount: 100,
createdAt: new Date(),
updatedAt: new Date()
};
const result = OrderSchema.safeParse(validOrder);
expect(result.success).toBe(true);
});
});
describe('Message Schema', () => {
it('should validate valid message', () => {
const validMessage = {
type: 'COLLECT_ORDERS',
payload: { shopId: 'shop1' },
traceId: 'trace-123'
};
const result = BaseMessageSchema.safeParse(validMessage);
expect(result.success).toBe(true);
});
it('should reject invalid message type', () => {
const invalidMessage = {
type: 'INVALID_TYPE',
payload: {}
};
const result = BaseMessageSchema.safeParse(invalidMessage);
expect(result.success).toBe(false);
});
it('should validate message response', () => {
const validResponse = {
success: true,
data: { orders: [] },
traceId: 'trace-123'
};
const result = MessageResponseSchema.safeParse(validResponse);
expect(result.success).toBe(true);
});
it('should validate error response', () => {
const errorResponse = {
success: false,
error: {
code: 'ERROR_001',
message: 'Something went wrong'
},
traceId: 'trace-123'
};
const result = MessageResponseSchema.safeParse(errorResponse);
expect(result.success).toBe(true);
});
});
describe('Type Inference', () => {
it('should infer correct types from schema', () => {
type User = z.infer<typeof UserSchema>;
type UserRole = z.infer<typeof UserRoleSchema>;
type UserStatus = z.infer<typeof UserStatusSchema>;
const user: User = {
id: '123',
name: 'Test',
email: 'test@example.com',
role: 'admin',
status: 'active',
createdAt: new Date(),
updatedAt: new Date()
};
expect(user.role).toBe('admin');
expect(user.status).toBe('active');
});
});
describe('Schema Extensions', () => {
it('should extend schema correctly', () => {
const ExtendedUserSchema = UserSchema.extend({
department: z.string()
});
const validExtendedUser = {
id: '123',
name: 'John',
email: 'john@example.com',
role: 'admin',
status: 'active',
department: 'Engineering',
createdAt: new Date(),
updatedAt: new Date()
};
const result = ExtendedUserSchema.safeParse(validExtendedUser);
expect(result.success).toBe(true);
});
it('should pick fields from schema', () => {
const UserPreviewSchema = UserSchema.pick({
id: true,
name: true,
email: true
});
const validPreview = {
id: '123',
name: 'John',
email: 'john@example.com'
};
const result = UserPreviewSchema.safeParse(validPreview);
expect(result.success).toBe(true);
});
it('should make schema partial', () => {
const PartialUserSchema = UserSchema.partial();
const validPartial = {
name: 'John'
};
const result = PartialUserSchema.safeParse(validPartial);
expect(result.success).toBe(true);
});
});