fork of hey-api/openapi-ts because I need some additional things
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #348 from hey-api/chore/compiler-type-cleanup

chore: compiler type generation cleanup

authored by

Jordan Shatford and committed by
GitHub
54244935 d5aa3b79

+46 -34
+3
.gitignore
··· 16 16 # test files 17 17 test/generated 18 18 test/e2e/generated 19 + 20 + # error files 21 + openapi-ts-error-*
+4 -1
packages/openapi-ts/src/compiler/index.ts
··· 9 9 10 10 export type { Property } from './typedef'; 11 11 export type { Comments } from './utils'; 12 - export type { Node } from 'typescript'; 12 + export type { Node, TypeNode } from 'typescript'; 13 13 14 14 export class TypeScriptFile { 15 15 private _headers: Array<string> = []; ··· 74 74 array: types.createArrayType, 75 75 enum: types.createEnumDeclaration, 76 76 object: types.createObjectType, 77 + }, 78 + utils: { 79 + toString: tsNodeToString, 77 80 }, 78 81 };
+18 -13
packages/openapi-ts/src/compiler/typedef.ts
··· 2 2 3 3 import { addLeadingComment, type Comments } from './utils'; 4 4 5 - export const createTypeNode = (base: any) => ts.factory.createTypeReferenceNode(base as string); 5 + export const createTypeNode = (base: any | ts.TypeNode) => 6 + ts.isTypeNode(base) ? base : ts.factory.createTypeReferenceNode(base); 6 7 7 8 /** 8 9 * Create a type alias declaration. Example `export type X = Y;`. ··· 13 14 */ 14 15 export const createTypeAliasDeclaration = ( 15 16 name: string, 16 - type: string, 17 + type: string | ts.TypeNode, 17 18 comments?: Comments 18 19 ): ts.TypeAliasDeclaration => { 19 20 const node = ts.factory.createTypeAliasDeclaration( 20 21 [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], 21 22 ts.factory.createIdentifier(name), 22 23 [], 23 - ts.factory.createTypeReferenceNode(type) 24 + createTypeNode(type) 24 25 ); 25 26 if (comments?.length) { 26 27 addLeadingComment(node, comments); ··· 31 32 // Property of a interface type node. 32 33 export type Property = { 33 34 name: string; 34 - type: string | undefined; 35 + type: any | ts.TypeNode; 35 36 isRequired?: boolean; 36 37 isReadOnly?: boolean; 37 38 comment?: Comments; ··· 50 51 property.isReadOnly ? [ts.factory.createModifier(ts.SyntaxKind.ReadonlyKeyword)] : undefined, 51 52 property.name, 52 53 property.isRequired ? undefined : ts.factory.createToken(ts.SyntaxKind.QuestionToken), 53 - ts.factory.createTypeReferenceNode(property.type ?? 'undefined') 54 + createTypeNode(property.type) 54 55 ); 55 56 const comment = property.comment; 56 57 if (comment) { ··· 71 72 * @param isNullable - if the whole type can be null 72 73 * @returns ts.UnionTypeNode 73 74 */ 74 - export const createTypeUnionNode = (types: unknown[], isNullable: boolean = false) => { 75 - const nodes = types.map(t => ts.factory.createTypeReferenceNode(t as string)); 75 + export const createTypeUnionNode = (types: (any | ts.TypeNode)[], isNullable: boolean = false) => { 76 + const nodes = types.map(t => createTypeNode(t)); 76 77 if (isNullable) { 77 78 nodes.push(ts.factory.createTypeReferenceNode('null')); 78 79 } ··· 85 86 * @param isNullable - if the whole type can be null 86 87 * @returns ts.IntersectionTypeNode | ts.UnionTypeNode 87 88 */ 88 - export const createTypeIntersectNode = (types: unknown[], isNullable: boolean = false) => { 89 - const nodes = types.map(t => ts.factory.createTypeReferenceNode(t as string)); 89 + export const createTypeIntersectNode = (types: (any | ts.TypeNode)[], isNullable: boolean = false) => { 90 + const nodes = types.map(t => createTypeNode(t)); 90 91 const intersect = ts.factory.createIntersectionTypeNode(nodes); 91 92 if (isNullable) { 92 93 return ts.factory.createUnionTypeNode([intersect, ts.factory.createTypeReferenceNode('null')]); ··· 100 101 * @param isNullable - if the whole type can be null 101 102 * @returns ts.UnionTypeNode 102 103 */ 103 - export const createTypeTupleNode = (types: unknown[], isNullable: boolean = false) => { 104 - const nodes = types.map(t => ts.factory.createTypeReferenceNode(t as string)); 104 + export const createTypeTupleNode = (types: (any | ts.TypeNode)[], isNullable: boolean = false) => { 105 + const nodes = types.map(t => createTypeNode(t)); 105 106 if (isNullable) { 106 107 nodes.push(ts.factory.createTypeReferenceNode('null')); 107 108 } ··· 115 116 * @param isNullable - if the whole type can be null 116 117 * @returns ts.TypeReferenceNode | ts.UnionTypeNode 117 118 */ 118 - export const createTypeRecordNode = (keys: unknown[], values: unknown[], isNullable: boolean = false) => { 119 + export const createTypeRecordNode = ( 120 + keys: (any | ts.TypeNode)[], 121 + values: (any | ts.TypeNode)[], 122 + isNullable: boolean = false 123 + ) => { 119 124 const keyNode = createTypeUnionNode(keys); 120 125 const valueNode = createTypeUnionNode(values); 121 126 const node = ts.factory.createTypeReferenceNode('Record', [keyNode, valueNode]); ··· 131 136 * @param isNullable - if the whole type can be null 132 137 * @returns ts.TypeReferenceNode | ts.UnionTypeNode 133 138 */ 134 - export const createTypeArrayNode = (types: unknown[], isNullable: boolean = false) => { 139 + export const createTypeArrayNode = (types: (any | ts.TypeNode)[], isNullable: boolean = false) => { 135 140 const node = ts.factory.createTypeReferenceNode('Array', [createTypeUnionNode(types)]); 136 141 if (!isNullable) { 137 142 return node;
+3 -4
packages/openapi-ts/src/utils/write/models.ts
··· 60 60 model.description && escapeComment(model.description), 61 61 model.deprecated && '@deprecated', 62 62 ]; 63 - const type = toType(model); 64 - return compiler.typedef.alias(model.name, type!, comment); 63 + return compiler.typedef.alias(model.name, toType(model), comment); 65 64 }; 66 65 67 66 const processModel = (client: Client, model: Model) => { ··· 120 119 } 121 120 122 121 operation.results.forEach(result => { 123 - resMap.set(result.code, toType(result)!); 122 + resMap.set(result.code, compiler.utils.toString(toType(result))); 124 123 }); 125 124 } 126 125 } ··· 235 234 type: '', 236 235 }); 237 236 const namespace = serviceExportedNamespace(); 238 - return compiler.typedef.alias(namespace, type!); 237 + return compiler.typedef.alias(namespace, type); 239 238 }; 240 239 241 240 /**
+18 -16
packages/openapi-ts/src/utils/write/type.ts
··· 1 - import { compiler, type Property } from '../../compiler'; 2 - import { tsNodeToString } from '../../compiler/utils'; 1 + import { compiler, type Property, type TypeNode } from '../../compiler'; 3 2 import { Model } from '../../openApi'; 4 3 import { getConfig } from '../config'; 5 - import { enumUnionType } from '../enum'; 4 + import { enumValue } from '../enum'; 6 5 import { escapeComment } from '../escape'; 7 6 import { modelIsRequired } from '../required'; 8 7 import { unique } from '../unique'; ··· 30 29 model.maxItems === model.minItems && 31 30 model.maxItems <= 100 32 31 ) { 33 - const types = toType(model.link); 34 - const tuple = compiler.typedef.tuple(Array(model.maxItems).fill(types), model.isNullable); 32 + const types = Array(model.maxItems).fill(toType(model.link)); 33 + const tuple = compiler.typedef.tuple(types, model.isNullable); 35 34 return tuple; 36 35 } 37 36 ··· 42 41 return compiler.typedef.array([base(model)], model.isNullable); 43 42 }; 44 43 45 - const typeEnum = (model: Model) => `${enumUnionType(model.enum)}${model.isNullable ? ' | null' : ''}`; 44 + const typeEnum = (model: Model) => { 45 + const values = model.enum.map(enumerator => enumValue(enumerator.value)); 46 + return compiler.typedef.union(values, model.isNullable); 47 + }; 46 48 47 49 const typeDict = (model: Model) => { 48 50 const type = model.link ? toType(model.link) : base(model); ··· 51 53 52 54 const typeUnion = (model: Model) => { 53 55 const models = model.properties; 54 - const types = models.map(m => toType(m)).filter(unique); 56 + const types = models.map(m => compiler.utils.toString(toType(m))).filter(unique); 55 57 return compiler.typedef.union(types, model.isNullable); 56 58 }; 57 59 58 60 const typeIntersect = (model: Model) => { 59 - const types = model.properties.map(m => toType(m)).filter(unique); 61 + const types = model.properties.map(m => compiler.utils.toString(toType(m))).filter(unique); 60 62 return compiler.typedef.intersect(types, model.isNullable); 61 63 }; 62 64 ··· 71 73 // special case for additional properties type 72 74 if (property.name === '[key: string]' && maybeRequired) { 73 75 maybeRequired = ''; 74 - value = tsNodeToString(compiler.typedef.union([value, 'undefined'])); 76 + value = compiler.typedef.union([value, 'undefined']); 75 77 } 76 78 return { 77 79 comment: [ ··· 88 90 return compiler.typedef.interface(properties, model.isNullable); 89 91 }; 90 92 91 - export const toType = (model: Model): string | undefined => { 93 + export const toType = (model: Model): TypeNode => { 92 94 switch (model.export) { 93 95 case 'all-of': 94 - return tsNodeToString(typeIntersect(model)); 96 + return typeIntersect(model); 95 97 case 'any-of': 96 98 case 'one-of': 97 - return tsNodeToString(typeUnion(model)); 99 + return typeUnion(model); 98 100 case 'array': 99 - return tsNodeToString(typeArray(model)); 101 + return typeArray(model); 100 102 case 'dictionary': 101 - return tsNodeToString(typeDict(model)); 103 + return typeDict(model); 102 104 case 'enum': 103 105 return typeEnum(model); 104 106 case 'interface': 105 - return tsNodeToString(typeInterface(model)); 107 + return typeInterface(model); 106 108 case 'reference': 107 109 default: 108 - return tsNodeToString(typeReference(model)); 110 + return typeReference(model); 109 111 } 110 112 };