Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for intersection type #482

Merged
merged 3 commits into from
Apr 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/lib/converter/plugins/TypePlugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Reflection, ReflectionKind, Decorator, DeclarationReflection, DeclarationHierarchy} from '../../models/reflections/index';
import {Type, ReferenceType, TupleType, UnionType} from '../../models/types/index';
import {Type, ReferenceType, TupleType, UnionType, IntersectionType} from '../../models/types/index';
import {Component, ConverterComponent} from '../components';
import {Converter} from '../converter';
import {Context} from '../context';
Expand Down Expand Up @@ -108,10 +108,10 @@ export class TypePlugin extends ConverterComponent {
for (let index = 0, count = tupleType.elements.length; index < count; index++) {
resolveType(reflection, tupleType.elements[index]);
}
} else if (type instanceof UnionType) {
const unionType: UnionType = <UnionType> type;
for (let index = 0, count = unionType.types.length; index < count; index++) {
resolveType(reflection, unionType.types[index]);
} else if (type instanceof UnionType || type instanceof IntersectionType) {
const unionOrIntersectionType: UnionType | IntersectionType = <UnionType | IntersectionType> type;
for (let index = 0, count = unionOrIntersectionType.types.length; index < count; index++) {
resolveType(reflection, unionOrIntersectionType.types[index]);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/converter/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ export {ReferenceConverter} from './reference';
export {ThisConverter} from './this';
export {TupleConverter} from './tuple';
export {TypeParameterConverter} from './type-parameter';
export {UnionConverter} from './union';
export {UnionOrIntersectionConverter} from './union-or-intersection';
export {UnknownConverter} from './unknown';
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
import * as ts from 'typescript';

import {Type, UnionType} from '../../models/types/index';
import {Type, UnionType, IntersectionType} from '../../models/types/index';
import {Component, ConverterTypeComponent, TypeConverter} from '../components';
import {Context} from '../context';

@Component({name: 'type:union'})
export class UnionConverter extends ConverterTypeComponent implements TypeConverter<ts.UnionType, ts.UnionTypeNode> {
@Component({name: 'type:union-or-intersection'})
export class UnionOrIntersectionConverter extends ConverterTypeComponent implements TypeConverter<ts.UnionOrIntersectionType, ts.UnionOrIntersectionTypeNode> {
/**
* Test whether this converter can handle the given TypeScript node.
*/
supportsNode(context: Context, node: ts.UnionTypeNode): boolean {
return node.kind === ts.SyntaxKind.UnionType;
supportsNode(context: Context, node: ts.UnionOrIntersectionTypeNode): boolean {
return node.kind === ts.SyntaxKind.UnionType || node.kind === ts.SyntaxKind.IntersectionType;
}

/**
* Test whether this converter can handle the given TypeScript type.
*/
supportsType(context: Context, type: ts.UnionType): boolean {
return !!(type.flags & ts.TypeFlags.Union);
supportsType(context: Context, type: ts.UnionOrIntersectionType): boolean {
return !!(type.flags & ts.TypeFlags.UnionOrIntersection);
}

/**
* Convert the given union type node to its type reflection.
*
* This is a node based converter, see [[convertUnionType]] for the type equivalent.
* This is a node based converter, see [[convertType]] for the type equivalent.
*
* ```
* let someValue: string|number;
* ```
*
* @param context The context object describing the current state the converter is in.
* @param node The union type node that should be converted.
* @param node The union or intersection type node that should be converted.
* @returns The type reflection representing the given union type node.
*/
convertNode(context: Context, node: ts.UnionTypeNode): UnionType {
convertNode(context: Context, node: ts.UnionOrIntersectionTypeNode): UnionType | IntersectionType {
let types: Type[] = [];
if (node.types) {
types = node.types.map((n) => this.owner.convertType(context, n));
} else {
types = [];
}

return new UnionType(types);
return node.kind === ts.SyntaxKind.IntersectionType ? new IntersectionType(types) : new UnionType(types);
}

/**
Expand All @@ -57,14 +57,14 @@ export class UnionConverter extends ConverterTypeComponent implements TypeConver
* @param type The union type that should be converted.
* @returns The type reflection representing the given union type.
*/
convertType(context: Context, type: ts.UnionType): UnionType {
convertType(context: Context, type: ts.UnionOrIntersectionType): UnionType | IntersectionType {
let types: Type[];
if (type && type.types) {
types = type.types.map((t) => this.owner.convertType(context, null, t));
} else {
types = [];
}

return new UnionType(types);
return !!(type.flags & ts.TypeFlags.Intersection) ? new IntersectionType(types) : new UnionType(types);
}
}
7 changes: 6 additions & 1 deletion src/lib/models/types/abstract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ export abstract class Type {
*/
isArray = false;

/**
* The type name identifier.
*/
readonly type: string = 'void';

/**
* Clone this type.
*
Expand All @@ -31,7 +36,7 @@ export abstract class Type {
*/
toObject(): any {
let result: any = {};
result.type = 'void';
result.type = this.type;

if (this.isArray) {
result.isArray = this.isArray;
Expand Down
1 change: 1 addition & 0 deletions src/lib/models/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export {Type} from './abstract';
export {IntrinsicType} from './intrinsic';
export {IntersectionType} from './intersection';
export {ReferenceType} from './reference';
export {ReflectionType} from './reflection';
export {StringLiteralType} from './string-literal';
Expand Down
82 changes: 82 additions & 0 deletions src/lib/models/types/intersection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {Type} from './abstract';

/**
* Represents an intersection type.
*
* ~~~
* let value: A & B;
* ~~~
*/
export class IntersectionType extends Type {
/**
* The types this union consists of.
*/
types: Type[];

/**
* The type name identifier.
*/
readonly type: string = 'intersection';

/**
* Create a new TupleType instance.
*
* @param types The types this union consists of.
*/
constructor(types: Type[]) {
super();
this.types = types;
}

/**
* Clone this type.
*
* @return A clone of this type.
*/
clone(): Type {
const clone = new IntersectionType(this.types);
clone.isArray = this.isArray;
return clone;
}

/**
* Test whether this type equals the given type.
*
* @param type The type that should be checked for equality.
* @returns TRUE if the given type equals this type, FALSE otherwise.
*/
equals(type: IntersectionType): boolean {
if (!(type instanceof IntersectionType)) {
return false;
}
if (type.isArray !== this.isArray) {
return false;
}
return Type.isTypeListSimiliar(type.types, this.types);
}

/**
* Return a raw object representation of this type.
*/
toObject(): any {
const result: any = super.toObject();

if (this.types && this.types.length) {
result.types = this.types.map((e) => e.toObject());
}

return result;
}

/**
* Return a string representation of this type.
*/
toString() {
const names: string[] = [];
this.types.forEach((element) => {
names.push(element.toString());
});

return names.join(' & ');
}
}
6 changes: 5 additions & 1 deletion src/lib/models/types/intrinsic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export class IntrinsicType extends Type {
*/
name: string;

/**
* The type name identifier.
*/
readonly type: string = 'instrinct'; // TODO: Is there any change to correct this typo?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think we should do here? I'm happy to accept the fix in a future PR. Just let me know what you think is needed to fix this!


/**
* Create a new instance of IntrinsicType.
*
Expand Down Expand Up @@ -51,7 +56,6 @@ export class IntrinsicType extends Type {
*/
toObject(): any {
const result: any = super.toObject();
result.type = 'instrinct';
result.name = this.name;
return result;
}
Expand Down
6 changes: 5 additions & 1 deletion src/lib/models/types/reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import {Type} from './abstract';
* ~~~
*/
export class ReferenceType extends Type {
/**
* The type name identifier.
*/
readonly type: string = 'reference';

/**
* The name of the referenced type.
*
Expand Down Expand Up @@ -90,7 +95,6 @@ export class ReferenceType extends Type {
*/
toObject(): any {
const result: any = super.toObject();
result.type = 'reference';
result.name = this.name;

if (this.reflection) {
Expand Down
6 changes: 5 additions & 1 deletion src/lib/models/types/reflection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ export class ReflectionType extends Type {
*/
declaration: DeclarationReflection;

/**
* The type name identifier.
*/
readonly type: string = 'reflection';

/**
* Create a new instance of ReflectionType.
*
Expand Down Expand Up @@ -50,7 +55,6 @@ export class ReflectionType extends Type {
*/
toObject(): any {
const result: any = super.toObject();
result.type = 'reflection';

if (this.declaration) {
result.declaration = this.declaration.toObject();
Expand Down
6 changes: 5 additions & 1 deletion src/lib/models/types/string-literal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export class StringLiteralType extends Type {
*/
value: string;

/**
* The type name identifier.
*/
readonly type: string = 'stringLiteral';

/**
* Create a new instance of StringLiteralType.
*
Expand Down Expand Up @@ -51,7 +56,6 @@ export class StringLiteralType extends Type {
*/
toObject(): any {
const result: any = super.toObject();
result.type = 'stringLiteral';
result.value = this.value;
return result;
}
Expand Down
6 changes: 5 additions & 1 deletion src/lib/models/types/tuple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export class TupleType extends Type {
*/
elements: Type[];

/**
* The type name identifier.
*/
readonly type: string = 'tuple';

/**
* Create a new TupleType instance.
*
Expand Down Expand Up @@ -55,7 +60,6 @@ export class TupleType extends Type {
*/
toObject(): any {
const result: any = super.toObject();
result.type = 'tuple';

if (this.elements && this.elements.length) {
result.elements = this.elements.map((e) => e.toObject());
Expand Down
6 changes: 5 additions & 1 deletion src/lib/models/types/type-parameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export class TypeParameterType extends Type {

constraint: Type;

/**
* The type name identifier.
*/
readonly type: string = 'typeParameter';

/**
* Clone this type.
*
Expand Down Expand Up @@ -57,7 +62,6 @@ export class TypeParameterType extends Type {
*/
toObject(): any {
const result: any = super.toObject();
result.type = 'typeParameter';
result.name = this.name;

if (this.constraint) {
Expand Down
6 changes: 5 additions & 1 deletion src/lib/models/types/union.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export class UnionType extends Type {
*/
types: Type[];

/**
* The type name identifier.
*/
readonly type: string = 'union';

/**
* Create a new TupleType instance.
*
Expand Down Expand Up @@ -55,7 +60,6 @@ export class UnionType extends Type {
*/
toObject(): any {
const result: any = super.toObject();
result.type = 'union';

if (this.types && this.types.length) {
result.types = this.types.map((e) => e.toObject());
Expand Down
6 changes: 5 additions & 1 deletion src/lib/models/types/unknown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ export class UnknownType extends Type {
*/
name: string;

/**
* The type name identifier.
*/
readonly type: string = 'unknown';

/**
* Create a new instance of UnknownType.
*
Expand Down Expand Up @@ -47,7 +52,6 @@ export class UnknownType extends Type {
*/
toObject(): any {
const result: any = super.toObject();
result.type = 'unknown';
result.name = this.name;
return result;
}
Expand Down
Loading