refactor: avoid readonly in nested types

This commit is contained in:
hypercross 2026-04-17 14:53:49 +08:00
parent 075045223f
commit c8f0d6b0de
3 changed files with 15 additions and 16 deletions

View File

@ -497,7 +497,7 @@ describe('parseCsv - type generation', () => {
currentFilePath: path.join(fixturesDir, 'test.csv'), currentFilePath: path.join(fixturesDir, 'test.csv'),
}); });
expect(result.typeDefinition).toContain('readonly items: readonly Parts[]'); expect(result.typeDefinition).toContain('readonly items: Parts[]');
}); });
it('should generate correct type for reference in tuple', () => { it('should generate correct type for reference in tuple', () => {

View File

@ -510,29 +510,29 @@ function schemaToTypeString(schema: Schema, resourceNames?: Map<string, string>)
case 'reference': { case 'reference': {
const typeName = resourceNames?.get(schema.tableName) || const typeName = resourceNames?.get(schema.tableName) ||
schema.tableName.charAt(0).toUpperCase() + schema.tableName.slice(1); schema.tableName.charAt(0).toUpperCase() + schema.tableName.slice(1);
const baseType = schema.isArray ? `readonly ${typeName}[]` : typeName; const baseType = schema.isArray ? `${typeName}[]` : typeName;
return schema.isOptional ? `${baseType} | null` : baseType; return schema.isOptional ? `${baseType} | null` : baseType;
} }
case 'array': case 'array':
if (schema.element.type === 'tuple') { if (schema.element.type === 'tuple') {
const tupleElements = schema.element.elements.map((el) => { const tupleElements = schema.element.elements.map((el) => {
const typeStr = schemaToTypeString(el.schema, resourceNames); const typeStr = schemaToTypeString(el.schema, resourceNames);
return el.name ? `readonly ${el.name}: ${typeStr}` : typeStr; return el.name ? `${el.name}: ${typeStr}` : typeStr;
}); });
return `readonly [${tupleElements.join(', ')}]`; return `[${tupleElements.join(', ')}]`;
} }
// Wrap union types in parentheses to maintain correct precedence // Wrap union types in parentheses to maintain correct precedence
const elementType = schemaToTypeString(schema.element, resourceNames); const elementType = schemaToTypeString(schema.element, resourceNames);
if (schema.element.type === 'union') { if (schema.element.type === 'union') {
return `readonly (${elementType})[]`; return `(${elementType})[]`;
} }
return `readonly ${elementType}[]`; return `${elementType}[]`;
case 'tuple': case 'tuple':
const tupleElements = schema.elements.map((el) => { const tupleElements = schema.elements.map((el) => {
const typeStr = schemaToTypeString(el.schema, resourceNames); const typeStr = schemaToTypeString(el.schema, resourceNames);
return el.name ? `readonly ${el.name}: ${typeStr}` : typeStr; return el.name ? `${el.name}: ${typeStr}` : typeStr;
}); });
return `readonly [${tupleElements.join(', ')}]`; return `[${tupleElements.join(', ')}]`;
default: default:
return 'unknown'; return 'unknown';
} }

View File

@ -150,15 +150,15 @@ describe('Type generation for string literals and unions', () => {
case 'array': case 'array':
const elemType = toType(s.element); const elemType = toType(s.element);
if (s.element.type === 'union') { if (s.element.type === 'union') {
return `readonly (${elemType})[]`; return `(${elemType})[]`;
} }
return `readonly ${elemType}[]`; return `${elemType}[]`;
case 'tuple': case 'tuple':
const elements = s.elements.map(el => { const elements = s.elements.map(el => {
const typeStr = toType(el.schema); const typeStr = toType(el.schema);
return el.name ? `readonly ${el.name}: ${typeStr}` : typeStr; return el.name ? `${el.name}: ${typeStr}` : typeStr;
}); });
return `readonly [${elements.join(', ')}]`; return `[${elements.join(', ')}]`;
default: return 'unknown'; default: return 'unknown';
} }
} }
@ -177,19 +177,18 @@ describe('Type generation for string literals and unions', () => {
it('should generate correct type for array of string literals', () => { it('should generate correct type for array of string literals', () => {
const schema = parseSchema('"item"[]'); const schema = parseSchema('"item"[]');
expect(generateType(schema)).toBe('readonly "item"[]'); expect(generateType(schema)).toBe('"item"[]');
}); });
it('should generate correct type for array of unions', () => { it('should generate correct type for array of unions', () => {
const schema = parseSchema('("pending" | "approved" | "rejected")[]'); const schema = parseSchema('("pending" | "approved" | "rejected")[]');
// Union types in arrays need parentheses for correct precedence // Union types in arrays need parentheses for correct precedence
expect(generateType(schema)).toBe('readonly ("pending" | "approved" | "rejected")[]'); expect(generateType(schema)).toBe('("pending" | "approved" | "rejected")[]');
}); });
it('should generate correct type for tuple with union field', () => { it('should generate correct type for tuple with union field', () => {
const schema = parseSchema('[name: string; status: "active" | "inactive"]'); const schema = parseSchema('[name: string; status: "active" | "inactive"]');
// Note: tuple elements have readonly modifier expect(generateType(schema)).toBe('[name: string, status: "active" | "inactive"]');
expect(generateType(schema)).toBe('readonly [readonly name: string, readonly status: "active" | "inactive"]');
}); });
it('should generate correct type for complex union', () => { it('should generate correct type for complex union', () => {