Skip to content

Commit

Permalink
feat: Add Type.getConstraint() and getDefault().
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret committed Mar 17, 2018
1 parent 8c5dafc commit 8850266
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 1 deletion.
30 changes: 30 additions & 0 deletions src/compiler/type/Type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,36 @@ export class Type<TType extends ts.Type = ts.Type> {
return this.compilerType.getConstructSignatures().map(s => this.global.compilerFactory.getSignature(s));
}

/**
* Gets the constraint or throws if it doesn't exist.
*/
getConstraintOrThrow() {
return errors.throwIfNullOrUndefined(this.getConstraint(), "Expected to find a constraint.");
}

/**
* Gets the constraint or returns undefined if it doesn't exist.
*/
getConstraint() {
const constraint = this.compilerType.getConstraint();
return constraint == null ? undefined : this.global.compilerFactory.getType(constraint);
}

/**
* Gets the default type or throws if it doesn't exist.
*/
getDefaultOrThrow() {
return errors.throwIfNullOrUndefined(this.getDefault(), "Expected to find a constraint.");
}

/**
* Gets the default type or returns undefined if it doesn't exist.
*/
getDefault() {
const defaultType = this.compilerType.getDefault();
return defaultType == null ? undefined : this.global.compilerFactory.getType(defaultType);
}

/**
* Gets the properties of the type.
*/
Expand Down
79 changes: 78 additions & 1 deletion src/tests/compiler/type/typeTests.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {expect} from "chai";
import {ts, TypeFlags, ObjectFlags, SymbolFlags, TypeFormatFlags} from "./../../../typescript";
import {Type, VariableStatement, Node, FunctionDeclaration} from "./../../../compiler";
import {Type, VariableStatement, Node, FunctionDeclaration, TypeAliasDeclaration} from "./../../../compiler";
import {VirtualFileSystemHost, DefaultFileSystemHost} from "./../../../fileSystem";
import {getInfoFromText} from "./../testHelpers";

Expand All @@ -14,6 +14,11 @@ describe(nameof(Type), () => {
return {...result, firstType: result.firstChild.getDeclarations()[0].getType()};
}

function getTypeAliasTypeFromText(text: string) {
const result = getInfoFromTextWithTypeChecking<TypeAliasDeclaration>(text);
return {...result, firstType: result.firstChild.getTypeNodeOrThrow().getType()};
}

describe(nameof<Type>(t => t.compilerType), () => {
it("should get the compiler type", () => {
const {firstType} = getTypeFromText("let myType: string;");
Expand Down Expand Up @@ -383,6 +388,78 @@ describe(nameof(Type), () => {
});
});

describe(nameof<Type>(t => t.getConstraint), () => {
function doTest(text: string, expected: string | undefined) {
const {firstType} = getTypeAliasTypeFromText(text);
if (expected == null)
expect(firstType.getConstraint()).to.be.undefined;
else
expect(firstType.getConstraint()!.getText()).to.equal(expected);
}

it("should get the constraint when it exists", () => {
doTest("type t<T extends string> = T;", "string");
});

it("should be undefined when it doesn't have a constraint", () => {
doTest("type t<T> = T;", undefined);
});
});

describe(nameof<Type>(t => t.getConstraintOrThrow), () => {
function doTest(text: string, expected: string | undefined) {
const {firstType} = getTypeAliasTypeFromText(text);
if (expected == null)
expect(() => firstType.getConstraintOrThrow()).to.throw();
else
expect(firstType.getConstraintOrThrow().getText()).to.equal(expected);
}

it("should get the constraint when it exists", () => {
doTest("type t<T extends string> = T;", "string");
});

it("should be undefined when it doesn't have a constraint", () => {
doTest("type t<T> = T;", undefined);
});
});

describe(nameof<Type>(t => t.getDefault), () => {
function doTest(text: string, expected: string | undefined) {
const {firstType} = getTypeAliasTypeFromText(text);
if (expected == null)
expect(firstType.getDefault()).to.be.undefined;
else
expect(firstType.getDefault()!.getText()).to.equal(expected);
}

it("should get the default when it exists", () => {
doTest("type t<T = string> = T;", "string");
});

it("should be undefined when it doesn't have a default", () => {
doTest("type t<T> = T;", undefined);
});
});

describe(nameof<Type>(t => t.getDefaultOrThrow), () => {
function doTest(text: string, expected: string | undefined) {
const {firstType} = getTypeAliasTypeFromText(text);
if (expected == null)
expect(() => firstType.getDefaultOrThrow()).to.throw();
else
expect(firstType.getDefaultOrThrow().getText()).to.equal(expected);
}

it("should get the default when it exists", () => {
doTest("type t<T = string> = T;", "string");
});

it("should be undefined when it doesn't have a default", () => {
doTest("type t<T> = T;", undefined);
});
});

describe(nameof<Type>(t => t.getBaseTypes), () => {
it("should return the base types of a type", () => {
const {firstType} = getTypeFromText("let myType: MyInterface; interface MyInterface extends OtherInterface {}\ninterface OtherInterface");
Expand Down

0 comments on commit 8850266

Please sign in to comment.