Skip to content

Commit

Permalink
feat: #252 - Add Type.isNullable.
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret committed Feb 15, 2018
1 parent ee9a7b5 commit f2dfd1f
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 9 deletions.
18 changes: 18 additions & 0 deletions src/compiler/type/Type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,17 @@ export class Type<TType extends ts.Type = ts.Type> {
return getSymbolByNameOrFindFunction(this.getApparentProperties(), nameOrFindFunction);
}

/**
* Gets if the type is possibly null or undefined.
*/
isNullable() {
for (const type of this.getUnionTypes()) {
if (type.isNullType() || type.isUndefinedType())
return true;
}
return false;
}

/**
* Gets the non-nullable type.
*/
Expand Down Expand Up @@ -262,6 +273,13 @@ export class Type<TType extends ts.Type = ts.Type> {
return (this.compilerType.flags & TypeFlags.Intersection) !== 0;
}

/**
* Gets if this is the null type.
*/
isNullType() {
return (this.compilerType.flags & TypeFlags.Null) !== 0;
}

/**
* Gets if this is an object type.
*/
Expand Down
60 changes: 51 additions & 9 deletions src/tests/compiler/type/typeTests.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import {expect} from "chai";
import {ts, TypeFlags, ObjectFlags, SymbolFlags, TypeFormatFlags} from "./../../../typescript";
import {Type, VariableStatement} from "./../../../compiler";
import {Type, VariableStatement, Node, FunctionDeclaration} from "./../../../compiler";
import {VirtualFileSystemHost, DefaultFileSystemHost} from "./../../../fileSystem";
import {getInfoFromText} from "./../testHelpers";

describe(nameof(Type), () => {
function getInfoFromTextWithTypeChecking<T extends Node>(text: string) {
return getInfoFromText<T>(text, { host: new VirtualFileSystemHost(), includeLibDts: true, compilerOptions: { strictNullChecks: true } });
}

function getTypeFromText(text: string) {
const result = getInfoFromText<VariableStatement>(text, { host: new VirtualFileSystemHost(), includeLibDts: true });
const result = getInfoFromTextWithTypeChecking<VariableStatement>(text);
return {...result, firstType: result.firstChild.getDeclarations()[0].getType()};
}

Expand Down Expand Up @@ -324,16 +328,54 @@ describe(nameof(Type), () => {
});

describe(nameof<Type>(t => t.getNonNullableType), () => {
it("should return the original type for a type that's already non-nullable", () => {
const {firstType} = getTypeFromText("let myType: string;");
function doTest(typeStr: string, expected: string) {
const {firstType} = getTypeFromText(`let myType: ${typeStr};`);
const nonNullableType = firstType.getNonNullableType();
expect(nonNullableType.getText()).to.equal("string");
expect(nonNullableType.getText()).to.equal(expected);
}

it("should return the original type for a type that's already non-nullable", () => {
doTest("string", "string");
});

it("should return the non-nullable type for undefined", () => {
doTest("string | undefined", "string");
});

it("should return the non-nullable type for null", () => {
doTest("string | null", "string");
});

it("should return the non-nullable type for null and undefined", () => {
doTest("string | null | undefined", "string");
});
});

describe(nameof<Type>(t => t.isNullable), () => {
function doTest(typeStr: string, expected: boolean) {
const {firstType} = getTypeFromText(`let myType: ${typeStr};`);
expect(firstType.isNullable()).to.equal(expected);
}

it("should return false for a non-nullable type", () => {
doTest("string", false);
});

it("should return true for undefined", () => {
doTest("string | undefined", true);
});

it("should return true for null", () => {
doTest("string | null", true);
});

it("should return true for null and undefined", () => {
doTest("string | null | undefined", true);
});

it("should return the non-nullable type", () => {
const {firstType} = getTypeFromText("let myType: string | undefined;");
const nonNullableType = firstType.getNonNullableType()!;
expect(nonNullableType.getText()).to.equal("string");
it("should return true for an optional property", () => {
const {firstChild} = getInfoFromTextWithTypeChecking<FunctionDeclaration>("function test(param?: string) {}");
expect(firstChild.getParameters()[0].getType().isNullable()).to.equal(true);
});
});

Expand Down

0 comments on commit f2dfd1f

Please sign in to comment.