ts-class-to-openapi 1.1.3 → 1.2.1

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.
package/dist/index.esm.js CHANGED
@@ -113,6 +113,7 @@ class SchemaTransformer {
113
113
  const isPrimitive = this.isPrimitiveType(type);
114
114
  const isClassType = this.isClassType(member);
115
115
  const isArray = this.isArrayProperty(member);
116
+ const isTypeLiteral = this.isTypeLiteral(member);
116
117
  const property = {
117
118
  name: propertyName,
118
119
  type,
@@ -124,6 +125,7 @@ class SchemaTransformer {
124
125
  isClassType,
125
126
  isArray,
126
127
  isRef: false,
128
+ isTypeLiteral: isTypeLiteral,
127
129
  };
128
130
  // Check for self-referencing properties to mark as $ref
129
131
  if (property.isClassType) {
@@ -136,8 +138,25 @@ class SchemaTransformer {
136
138
  property.isRef = true;
137
139
  }
138
140
  }
139
- else {
140
- debugger;
141
+ }
142
+ if (property.isTypeLiteral &&
143
+ property.originalProperty.type &&
144
+ property.originalProperty.type
145
+ .typeArguments?.length === 1) {
146
+ const typeArguments = property.originalProperty.type.typeArguments;
147
+ if (typeArguments && typeArguments[0]) {
148
+ const firstTypeArg = typeArguments[0];
149
+ if (ts.isTypeReferenceNode(firstTypeArg)) {
150
+ const type = this.checker.getTypeAtLocation(firstTypeArg);
151
+ const symbol = type.getSymbol();
152
+ if (symbol && symbol.declarations) {
153
+ const classDeclaration = symbol.declarations.find(decl => ts.isClassDeclaration(decl));
154
+ if (classDeclaration &&
155
+ ts.isClassDeclaration(classDeclaration)) {
156
+ property.typeLiteralClassReference = classDeclaration;
157
+ }
158
+ }
159
+ }
141
160
  }
142
161
  }
143
162
  properties.push(property);
@@ -462,43 +481,113 @@ class SchemaTransformer {
462
481
  return false;
463
482
  }
464
483
  // Check if the original property type is an array type
465
- if (this.isArrayProperty(propertyDeclaration) &&
466
- ts.isTypeReferenceNode(propertyDeclaration.type
467
- .elementType)) {
468
- const type = this.checker.getTypeAtLocation(propertyDeclaration.type.elementType);
484
+ if (this.isArrayProperty(propertyDeclaration)) {
485
+ const arrayType = propertyDeclaration.type;
486
+ const elementType = arrayType.elementType;
487
+ // Special handling for utility types with type arguments (e.g., PayloadEntity<Person>)
488
+ if (ts.isTypeReferenceNode(elementType) &&
489
+ elementType.typeArguments &&
490
+ elementType.typeArguments.length > 0) {
491
+ // Check the first type argument - it might be the actual class
492
+ const firstTypeArg = elementType.typeArguments[0];
493
+ if (firstTypeArg) {
494
+ const argType = this.checker.getTypeAtLocation(firstTypeArg);
495
+ const argSymbol = argType.getSymbol();
496
+ if (argSymbol && argSymbol.declarations) {
497
+ const hasClass = argSymbol.declarations.some(decl => ts.isClassDeclaration(decl));
498
+ if (hasClass)
499
+ return true;
500
+ }
501
+ }
502
+ }
503
+ // Get the type from the element, regardless of its syntaxkind
504
+ const type = this.checker.getTypeAtLocation(elementType);
469
505
  const symbol = type.getSymbol();
470
506
  if (symbol && symbol.declarations) {
471
507
  return symbol.declarations.some(decl => ts.isClassDeclaration(decl));
472
508
  }
509
+ return false;
473
510
  }
474
- else if (ts.isTypeReferenceNode(propertyDeclaration.type)) {
511
+ // Check non-array types
512
+ else {
513
+ // Special handling for utility types with type arguments (e.g., PayloadEntity<Branch>)
514
+ if (ts.isTypeReferenceNode(propertyDeclaration.type) &&
515
+ propertyDeclaration.type.typeArguments &&
516
+ propertyDeclaration.type.typeArguments.length > 0) {
517
+ // Check the first type argument - it might be the actual class
518
+ const firstTypeArg = propertyDeclaration.type.typeArguments[0];
519
+ if (firstTypeArg) {
520
+ const argType = this.checker.getTypeAtLocation(firstTypeArg);
521
+ const argSymbol = argType.getSymbol();
522
+ if (argSymbol && argSymbol.declarations) {
523
+ const hasClass = argSymbol.declarations.some(decl => ts.isClassDeclaration(decl));
524
+ if (hasClass)
525
+ return true;
526
+ }
527
+ }
528
+ }
475
529
  const type = this.checker.getTypeAtLocation(propertyDeclaration.type);
476
530
  const symbol = type.getSymbol();
477
531
  if (symbol && symbol.declarations) {
478
532
  return symbol.declarations.some(decl => ts.isClassDeclaration(decl));
479
533
  }
534
+ return false;
480
535
  }
481
- return false;
482
536
  }
483
537
  getDeclarationProperty(property) {
484
538
  if (!property.originalProperty.type) {
485
539
  return undefined;
486
540
  }
487
- if (ts.isArrayTypeNode(property.originalProperty.type) &&
488
- ts.isTypeReferenceNode(property.originalProperty.type.elementType)) {
489
- const type = this.checker.getTypeAtLocation(property.originalProperty.type.elementType);
541
+ // Handle array types - get the element type
542
+ if (ts.isArrayTypeNode(property.originalProperty.type)) {
543
+ const elementType = property.originalProperty.type.elementType;
544
+ // Check if it's a utility type with type arguments (e.g., PayloadEntity<Branch>[])
545
+ if (ts.isTypeReferenceNode(elementType) &&
546
+ elementType.typeArguments &&
547
+ elementType.typeArguments.length > 0) {
548
+ const firstTypeArg = elementType.typeArguments[0];
549
+ if (firstTypeArg) {
550
+ const argType = this.checker.getTypeAtLocation(firstTypeArg);
551
+ const argSymbol = argType.getSymbol();
552
+ if (argSymbol && argSymbol.declarations) {
553
+ const classDecl = argSymbol.declarations.find(decl => ts.isClassDeclaration(decl));
554
+ if (classDecl)
555
+ return classDecl;
556
+ }
557
+ }
558
+ }
559
+ const type = this.checker.getTypeAtLocation(elementType);
490
560
  const symbol = type.getSymbol();
491
561
  if (symbol && symbol.declarations) {
492
- return symbol.declarations[0];
562
+ // Return the first class declaration found
563
+ const classDecl = symbol.declarations.find(decl => ts.isClassDeclaration(decl));
564
+ return classDecl || symbol.declarations[0];
493
565
  }
566
+ return undefined;
494
567
  }
495
- else if (ts.isTypeReferenceNode(property.originalProperty.type)) {
496
- const type = this.checker.getTypeAtLocation(property.originalProperty.type);
497
- const symbol = type.getSymbol();
498
- if (symbol && symbol.declarations) {
499
- return symbol.declarations[0];
568
+ // Handle non-array types
569
+ // Check if it's a utility type with type arguments (e.g., PayloadEntity<Branch>)
570
+ if (ts.isTypeReferenceNode(property.originalProperty.type) &&
571
+ property.originalProperty.type.typeArguments &&
572
+ property.originalProperty.type.typeArguments.length > 0) {
573
+ const firstTypeArg = property.originalProperty.type.typeArguments[0];
574
+ if (firstTypeArg) {
575
+ const argType = this.checker.getTypeAtLocation(firstTypeArg);
576
+ const argSymbol = argType.getSymbol();
577
+ if (argSymbol && argSymbol.declarations) {
578
+ const classDecl = argSymbol.declarations.find(decl => ts.isClassDeclaration(decl));
579
+ if (classDecl)
580
+ return classDecl;
581
+ }
500
582
  }
501
583
  }
584
+ const type = this.checker.getTypeAtLocation(property.originalProperty.type);
585
+ const symbol = type.getSymbol();
586
+ if (symbol && symbol.declarations) {
587
+ // Return the first class declaration found
588
+ const classDecl = symbol.declarations.find(decl => ts.isClassDeclaration(decl));
589
+ return classDecl || symbol.declarations[0];
590
+ }
502
591
  return undefined;
503
592
  }
504
593
  isArrayProperty(propertyDeclaration) {
@@ -534,34 +623,60 @@ class SchemaTransformer {
534
623
  schema = this.getSchemaFromPrimitive(property);
535
624
  }
536
625
  else if (property.isClassType) {
537
- const declaration = this.getDeclarationProperty(property);
538
- if (property.isRef && classDeclaration.name) {
539
- // Self-referencing property, handle as a reference to avoid infinite recursion
540
- if (property.isArray) {
541
- schema.type = 'array';
542
- schema.items = {
543
- $ref: `#/components/schemas/${classDeclaration.name.text}`,
544
- };
545
- }
546
- else {
547
- schema = {
548
- $ref: `#/components/schemas/${classDeclaration.name.text}`,
549
- };
550
- }
626
+ schema = this.buildSchemaFromClass({
627
+ property,
628
+ classDeclaration,
629
+ visitedClass,
630
+ transformedSchema,
631
+ });
632
+ }
633
+ else if (property.isTypeLiteral && property.typeLiteralClassReference) {
634
+ schema = this.buildSchemaFromClass({
635
+ property,
636
+ classDeclaration: property.typeLiteralClassReference,
637
+ visitedClass,
638
+ transformedSchema,
639
+ });
640
+ }
641
+ else {
642
+ schema = { type: 'object', properties: {}, additionalProperties: true };
643
+ }
644
+ this.applyDecorators(property, schema);
645
+ return schema;
646
+ }
647
+ buildSchemaFromClass({ property, classDeclaration, visitedClass, transformedSchema, }) {
648
+ const declaration = this.getDeclarationProperty(property);
649
+ let schema = {};
650
+ if (property.isRef && classDeclaration.name) {
651
+ // Self-referencing property, handle as a reference to avoid infinite recursion
652
+ if (property.isArray) {
653
+ schema.type = 'array';
654
+ schema.items = {
655
+ $ref: `#/components/schemas/${classDeclaration.name.text}`,
656
+ };
551
657
  }
552
658
  else {
553
- schema = this.getSchemaFromClass({
554
- isArray: property.isArray,
555
- visitedClass,
556
- transformedSchema,
557
- declaration,
558
- });
659
+ schema = {
660
+ $ref: `#/components/schemas/${classDeclaration.name.text}`,
661
+ };
559
662
  }
560
663
  }
664
+ else if (property.isTypeLiteral && property.typeLiteralClassReference) {
665
+ schema = this.getSchemaFromClass({
666
+ isArray: property.isArray,
667
+ visitedClass,
668
+ transformedSchema,
669
+ declaration: property.typeLiteralClassReference,
670
+ });
671
+ }
561
672
  else {
562
- schema = { type: 'object', properties: {}, additionalProperties: true };
673
+ schema = this.getSchemaFromClass({
674
+ isArray: property.isArray,
675
+ visitedClass,
676
+ transformedSchema,
677
+ declaration,
678
+ });
563
679
  }
564
- this.applyDecorators(property, schema);
565
680
  return schema;
566
681
  }
567
682
  getSchemaFromClass({ transformedSchema = new Map(), visitedClass = new Set(), declaration, isArray, }) {
@@ -664,6 +779,39 @@ class SchemaTransformer {
664
779
  }
665
780
  return propertySchema;
666
781
  }
782
+ isTypeLiteral(property) {
783
+ if (!property.type)
784
+ return false;
785
+ if (ts.isTypeReferenceNode(property.type)) {
786
+ const symbol = this.checker.getSymbolAtLocation(property.type.typeName);
787
+ if (symbol) {
788
+ const declarations = symbol.getDeclarations();
789
+ if (declarations && declarations.length > 0) {
790
+ const typeAliasDecl = declarations.find(decl => ts.isTypeAliasDeclaration(decl));
791
+ if (typeAliasDecl && typeAliasDecl.type) {
792
+ return this.isLiteralTypeNode(typeAliasDecl.type);
793
+ }
794
+ }
795
+ }
796
+ }
797
+ return false;
798
+ }
799
+ /**
800
+ *
801
+ * @param typeNode
802
+ * @returns boolean - true si el typeNode representa un tipo literal complejo
803
+ */
804
+ isLiteralTypeNode(typeNode) {
805
+ return (ts.isIntersectionTypeNode(typeNode) || // {} & Omit<T, ...>
806
+ ts.isUnionTypeNode(typeNode) || // string | number
807
+ ts.isMappedTypeNode(typeNode) || // { [K in keyof T]: ... }
808
+ ts.isTypeLiteralNode(typeNode) || // { foo: string }
809
+ ts.isConditionalTypeNode(typeNode) || // T extends U ? X : Y
810
+ ts.isIndexedAccessTypeNode(typeNode) || // T['key']
811
+ ts.isTypeOperatorNode(typeNode) || // keyof T, readonly T
812
+ ts.isTypeReferenceNode(typeNode) // Omit, Pick, Partial, etc.
813
+ );
814
+ }
667
815
  //Todo: implement properly
668
816
  applyEnumDecorator(decorator, schema) { }
669
817
  applyDecorators(property, schema) {
package/dist/index.js CHANGED
@@ -115,6 +115,7 @@ class SchemaTransformer {
115
115
  const isPrimitive = this.isPrimitiveType(type);
116
116
  const isClassType = this.isClassType(member);
117
117
  const isArray = this.isArrayProperty(member);
118
+ const isTypeLiteral = this.isTypeLiteral(member);
118
119
  const property = {
119
120
  name: propertyName,
120
121
  type,
@@ -126,6 +127,7 @@ class SchemaTransformer {
126
127
  isClassType,
127
128
  isArray,
128
129
  isRef: false,
130
+ isTypeLiteral: isTypeLiteral,
129
131
  };
130
132
  // Check for self-referencing properties to mark as $ref
131
133
  if (property.isClassType) {
@@ -138,8 +140,25 @@ class SchemaTransformer {
138
140
  property.isRef = true;
139
141
  }
140
142
  }
141
- else {
142
- debugger;
143
+ }
144
+ if (property.isTypeLiteral &&
145
+ property.originalProperty.type &&
146
+ property.originalProperty.type
147
+ .typeArguments?.length === 1) {
148
+ const typeArguments = property.originalProperty.type.typeArguments;
149
+ if (typeArguments && typeArguments[0]) {
150
+ const firstTypeArg = typeArguments[0];
151
+ if (ts.isTypeReferenceNode(firstTypeArg)) {
152
+ const type = this.checker.getTypeAtLocation(firstTypeArg);
153
+ const symbol = type.getSymbol();
154
+ if (symbol && symbol.declarations) {
155
+ const classDeclaration = symbol.declarations.find(decl => ts.isClassDeclaration(decl));
156
+ if (classDeclaration &&
157
+ ts.isClassDeclaration(classDeclaration)) {
158
+ property.typeLiteralClassReference = classDeclaration;
159
+ }
160
+ }
161
+ }
143
162
  }
144
163
  }
145
164
  properties.push(property);
@@ -464,43 +483,113 @@ class SchemaTransformer {
464
483
  return false;
465
484
  }
466
485
  // Check if the original property type is an array type
467
- if (this.isArrayProperty(propertyDeclaration) &&
468
- ts.isTypeReferenceNode(propertyDeclaration.type
469
- .elementType)) {
470
- const type = this.checker.getTypeAtLocation(propertyDeclaration.type.elementType);
486
+ if (this.isArrayProperty(propertyDeclaration)) {
487
+ const arrayType = propertyDeclaration.type;
488
+ const elementType = arrayType.elementType;
489
+ // Special handling for utility types with type arguments (e.g., PayloadEntity<Person>)
490
+ if (ts.isTypeReferenceNode(elementType) &&
491
+ elementType.typeArguments &&
492
+ elementType.typeArguments.length > 0) {
493
+ // Check the first type argument - it might be the actual class
494
+ const firstTypeArg = elementType.typeArguments[0];
495
+ if (firstTypeArg) {
496
+ const argType = this.checker.getTypeAtLocation(firstTypeArg);
497
+ const argSymbol = argType.getSymbol();
498
+ if (argSymbol && argSymbol.declarations) {
499
+ const hasClass = argSymbol.declarations.some(decl => ts.isClassDeclaration(decl));
500
+ if (hasClass)
501
+ return true;
502
+ }
503
+ }
504
+ }
505
+ // Get the type from the element, regardless of its syntaxkind
506
+ const type = this.checker.getTypeAtLocation(elementType);
471
507
  const symbol = type.getSymbol();
472
508
  if (symbol && symbol.declarations) {
473
509
  return symbol.declarations.some(decl => ts.isClassDeclaration(decl));
474
510
  }
511
+ return false;
475
512
  }
476
- else if (ts.isTypeReferenceNode(propertyDeclaration.type)) {
513
+ // Check non-array types
514
+ else {
515
+ // Special handling for utility types with type arguments (e.g., PayloadEntity<Branch>)
516
+ if (ts.isTypeReferenceNode(propertyDeclaration.type) &&
517
+ propertyDeclaration.type.typeArguments &&
518
+ propertyDeclaration.type.typeArguments.length > 0) {
519
+ // Check the first type argument - it might be the actual class
520
+ const firstTypeArg = propertyDeclaration.type.typeArguments[0];
521
+ if (firstTypeArg) {
522
+ const argType = this.checker.getTypeAtLocation(firstTypeArg);
523
+ const argSymbol = argType.getSymbol();
524
+ if (argSymbol && argSymbol.declarations) {
525
+ const hasClass = argSymbol.declarations.some(decl => ts.isClassDeclaration(decl));
526
+ if (hasClass)
527
+ return true;
528
+ }
529
+ }
530
+ }
477
531
  const type = this.checker.getTypeAtLocation(propertyDeclaration.type);
478
532
  const symbol = type.getSymbol();
479
533
  if (symbol && symbol.declarations) {
480
534
  return symbol.declarations.some(decl => ts.isClassDeclaration(decl));
481
535
  }
536
+ return false;
482
537
  }
483
- return false;
484
538
  }
485
539
  getDeclarationProperty(property) {
486
540
  if (!property.originalProperty.type) {
487
541
  return undefined;
488
542
  }
489
- if (ts.isArrayTypeNode(property.originalProperty.type) &&
490
- ts.isTypeReferenceNode(property.originalProperty.type.elementType)) {
491
- const type = this.checker.getTypeAtLocation(property.originalProperty.type.elementType);
543
+ // Handle array types - get the element type
544
+ if (ts.isArrayTypeNode(property.originalProperty.type)) {
545
+ const elementType = property.originalProperty.type.elementType;
546
+ // Check if it's a utility type with type arguments (e.g., PayloadEntity<Branch>[])
547
+ if (ts.isTypeReferenceNode(elementType) &&
548
+ elementType.typeArguments &&
549
+ elementType.typeArguments.length > 0) {
550
+ const firstTypeArg = elementType.typeArguments[0];
551
+ if (firstTypeArg) {
552
+ const argType = this.checker.getTypeAtLocation(firstTypeArg);
553
+ const argSymbol = argType.getSymbol();
554
+ if (argSymbol && argSymbol.declarations) {
555
+ const classDecl = argSymbol.declarations.find(decl => ts.isClassDeclaration(decl));
556
+ if (classDecl)
557
+ return classDecl;
558
+ }
559
+ }
560
+ }
561
+ const type = this.checker.getTypeAtLocation(elementType);
492
562
  const symbol = type.getSymbol();
493
563
  if (symbol && symbol.declarations) {
494
- return symbol.declarations[0];
564
+ // Return the first class declaration found
565
+ const classDecl = symbol.declarations.find(decl => ts.isClassDeclaration(decl));
566
+ return classDecl || symbol.declarations[0];
495
567
  }
568
+ return undefined;
496
569
  }
497
- else if (ts.isTypeReferenceNode(property.originalProperty.type)) {
498
- const type = this.checker.getTypeAtLocation(property.originalProperty.type);
499
- const symbol = type.getSymbol();
500
- if (symbol && symbol.declarations) {
501
- return symbol.declarations[0];
570
+ // Handle non-array types
571
+ // Check if it's a utility type with type arguments (e.g., PayloadEntity<Branch>)
572
+ if (ts.isTypeReferenceNode(property.originalProperty.type) &&
573
+ property.originalProperty.type.typeArguments &&
574
+ property.originalProperty.type.typeArguments.length > 0) {
575
+ const firstTypeArg = property.originalProperty.type.typeArguments[0];
576
+ if (firstTypeArg) {
577
+ const argType = this.checker.getTypeAtLocation(firstTypeArg);
578
+ const argSymbol = argType.getSymbol();
579
+ if (argSymbol && argSymbol.declarations) {
580
+ const classDecl = argSymbol.declarations.find(decl => ts.isClassDeclaration(decl));
581
+ if (classDecl)
582
+ return classDecl;
583
+ }
502
584
  }
503
585
  }
586
+ const type = this.checker.getTypeAtLocation(property.originalProperty.type);
587
+ const symbol = type.getSymbol();
588
+ if (symbol && symbol.declarations) {
589
+ // Return the first class declaration found
590
+ const classDecl = symbol.declarations.find(decl => ts.isClassDeclaration(decl));
591
+ return classDecl || symbol.declarations[0];
592
+ }
504
593
  return undefined;
505
594
  }
506
595
  isArrayProperty(propertyDeclaration) {
@@ -536,34 +625,60 @@ class SchemaTransformer {
536
625
  schema = this.getSchemaFromPrimitive(property);
537
626
  }
538
627
  else if (property.isClassType) {
539
- const declaration = this.getDeclarationProperty(property);
540
- if (property.isRef && classDeclaration.name) {
541
- // Self-referencing property, handle as a reference to avoid infinite recursion
542
- if (property.isArray) {
543
- schema.type = 'array';
544
- schema.items = {
545
- $ref: `#/components/schemas/${classDeclaration.name.text}`,
546
- };
547
- }
548
- else {
549
- schema = {
550
- $ref: `#/components/schemas/${classDeclaration.name.text}`,
551
- };
552
- }
628
+ schema = this.buildSchemaFromClass({
629
+ property,
630
+ classDeclaration,
631
+ visitedClass,
632
+ transformedSchema,
633
+ });
634
+ }
635
+ else if (property.isTypeLiteral && property.typeLiteralClassReference) {
636
+ schema = this.buildSchemaFromClass({
637
+ property,
638
+ classDeclaration: property.typeLiteralClassReference,
639
+ visitedClass,
640
+ transformedSchema,
641
+ });
642
+ }
643
+ else {
644
+ schema = { type: 'object', properties: {}, additionalProperties: true };
645
+ }
646
+ this.applyDecorators(property, schema);
647
+ return schema;
648
+ }
649
+ buildSchemaFromClass({ property, classDeclaration, visitedClass, transformedSchema, }) {
650
+ const declaration = this.getDeclarationProperty(property);
651
+ let schema = {};
652
+ if (property.isRef && classDeclaration.name) {
653
+ // Self-referencing property, handle as a reference to avoid infinite recursion
654
+ if (property.isArray) {
655
+ schema.type = 'array';
656
+ schema.items = {
657
+ $ref: `#/components/schemas/${classDeclaration.name.text}`,
658
+ };
553
659
  }
554
660
  else {
555
- schema = this.getSchemaFromClass({
556
- isArray: property.isArray,
557
- visitedClass,
558
- transformedSchema,
559
- declaration,
560
- });
661
+ schema = {
662
+ $ref: `#/components/schemas/${classDeclaration.name.text}`,
663
+ };
561
664
  }
562
665
  }
666
+ else if (property.isTypeLiteral && property.typeLiteralClassReference) {
667
+ schema = this.getSchemaFromClass({
668
+ isArray: property.isArray,
669
+ visitedClass,
670
+ transformedSchema,
671
+ declaration: property.typeLiteralClassReference,
672
+ });
673
+ }
563
674
  else {
564
- schema = { type: 'object', properties: {}, additionalProperties: true };
675
+ schema = this.getSchemaFromClass({
676
+ isArray: property.isArray,
677
+ visitedClass,
678
+ transformedSchema,
679
+ declaration,
680
+ });
565
681
  }
566
- this.applyDecorators(property, schema);
567
682
  return schema;
568
683
  }
569
684
  getSchemaFromClass({ transformedSchema = new Map(), visitedClass = new Set(), declaration, isArray, }) {
@@ -666,6 +781,39 @@ class SchemaTransformer {
666
781
  }
667
782
  return propertySchema;
668
783
  }
784
+ isTypeLiteral(property) {
785
+ if (!property.type)
786
+ return false;
787
+ if (ts.isTypeReferenceNode(property.type)) {
788
+ const symbol = this.checker.getSymbolAtLocation(property.type.typeName);
789
+ if (symbol) {
790
+ const declarations = symbol.getDeclarations();
791
+ if (declarations && declarations.length > 0) {
792
+ const typeAliasDecl = declarations.find(decl => ts.isTypeAliasDeclaration(decl));
793
+ if (typeAliasDecl && typeAliasDecl.type) {
794
+ return this.isLiteralTypeNode(typeAliasDecl.type);
795
+ }
796
+ }
797
+ }
798
+ }
799
+ return false;
800
+ }
801
+ /**
802
+ *
803
+ * @param typeNode
804
+ * @returns boolean - true si el typeNode representa un tipo literal complejo
805
+ */
806
+ isLiteralTypeNode(typeNode) {
807
+ return (ts.isIntersectionTypeNode(typeNode) || // {} & Omit<T, ...>
808
+ ts.isUnionTypeNode(typeNode) || // string | number
809
+ ts.isMappedTypeNode(typeNode) || // { [K in keyof T]: ... }
810
+ ts.isTypeLiteralNode(typeNode) || // { foo: string }
811
+ ts.isConditionalTypeNode(typeNode) || // T extends U ? X : Y
812
+ ts.isIndexedAccessTypeNode(typeNode) || // T['key']
813
+ ts.isTypeOperatorNode(typeNode) || // keyof T, readonly T
814
+ ts.isTypeReferenceNode(typeNode) // Omit, Pick, Partial, etc.
815
+ );
816
+ }
669
817
  //Todo: implement properly
670
818
  applyEnumDecorator(decorator, schema) { }
671
819
  applyDecorators(property, schema) {