Skip to content

Commit

Permalink
feat: #672 - Add Type#getPropertyOrThrow
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret committed Sep 1, 2019
1 parent 37476f8 commit c929c6c
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 10 deletions.
15 changes: 14 additions & 1 deletion lib/ts-morph.d.ts
Expand Up @@ -10818,11 +10818,24 @@ export declare class Type<TType extends ts.Type = ts.Type> {
*/
getProperties(): Symbol[];
/**
* Gets a property.
* Gets a property or throws if it doesn't exist.
* @param name - By a name.
*/
getPropertyOrThrow(name: string): Symbol;
/**
* Gets a property or throws if it doesn't exist.
* @param findFunction - Function for searching for a property.
*/
getPropertyOrThrow(findFunction: (declaration: Symbol) => boolean): Symbol;
/**
* Gets a property or returns undefined if it does not exist.
* @param name - By a name.
*/
getProperty(name: string): Symbol | undefined;
/**
* Gets a property or returns undefined if it does not exist.
* @param findFunction - Function for searching for a property.
*/
getProperty(findFunction: (declaration: Symbol) => boolean): Symbol | undefined;
/**
* Gets the apparent properties of the type.
Expand Down
26 changes: 24 additions & 2 deletions src/compiler/types/Type.ts
@@ -1,7 +1,7 @@
import * as errors from "../../errors";
import { ProjectContext } from "../../ProjectContext";
import { ObjectFlags, ts, TypeFlags, TypeFormatFlags } from "../../typescript";
import { getSymbolByNameOrFindFunction, TypeGuards } from "../../utils";
import { getSymbolByNameOrFindFunction, TypeGuards, getNotFoundErrorMessageForNameOrFindFunction } from "../../utils";
import { Signature, Symbol } from "../symbols";
import { Node } from "../ast";
import { TypeParameter } from "./TypeParameter";
Expand Down Expand Up @@ -153,12 +153,34 @@ export class Type<TType extends ts.Type = ts.Type> {
}

/**
* Gets a property.
* Gets a property or throws if it doesn't exist.
* @param name - By a name.
*/
getPropertyOrThrow(name: string): Symbol;
/**
* Gets a property or throws if it doesn't exist.
* @param findFunction - Function for searching for a property.
*/
getPropertyOrThrow(findFunction: (declaration: Symbol) => boolean): Symbol;
/** @internal */
getPropertyOrThrow(nameOrFindFunction: string | ((declaration: Symbol) => boolean)): Symbol;
getPropertyOrThrow(nameOrFindFunction: string | ((declaration: Symbol) => boolean)): Symbol {
return errors.throwIfNullOrUndefined(this.getProperty(nameOrFindFunction),
() => getNotFoundErrorMessageForNameOrFindFunction("symbol property", nameOrFindFunction));
}

/**
* Gets a property or returns undefined if it does not exist.
* @param name - By a name.
*/
getProperty(name: string): Symbol | undefined;
/**
* Gets a property or returns undefined if it does not exist.
* @param findFunction - Function for searching for a property.
*/
getProperty(findFunction: (declaration: Symbol) => boolean): Symbol | undefined;
/** @internal */
getProperty(nameOrFindFunction: string | ((declaration: Symbol) => boolean)): Symbol | undefined;
getProperty(nameOrFindFunction: string | ((declaration: Symbol) => boolean)): Symbol | undefined {
return getSymbolByNameOrFindFunction(this.getProperties(), nameOrFindFunction);
}
Expand Down
45 changes: 38 additions & 7 deletions src/tests/compiler/type/typeTests.ts
@@ -1,5 +1,5 @@
import { expect } from "chai";
import { FunctionDeclaration, Node, Type, TypeAliasDeclaration, VariableStatement } from "../../../compiler";
import { FunctionDeclaration, Node, Type, TypeAliasDeclaration, VariableStatement, Symbol } from "../../../compiler";
import { VirtualFileSystemHost } from "../../../fileSystem";
import { ObjectFlags, SymbolFlags, TypeFlags, TypeFormatFlags } from "../../../typescript";
import { getInfoFromText } from "../testHelpers";
Expand Down Expand Up @@ -720,17 +720,48 @@ let unknownType: unknown;
});
});

describe(nameof<Type>(t => t.getPropertyOrThrow), () => {
function doTest(text: string, nameOrFindFunction: string | ((declaration: Symbol) => boolean), expected: string | undefined) {
const { firstType } = getTypeFromText(text);
if (expected == null)
expect(() => firstType.getPropertyOrThrow(nameOrFindFunction)).to.throw();
else
expect(firstType.getPropertyOrThrow(nameOrFindFunction).getName()).to.equal(expected);
}

it("should get the property by name", () => {
doTest("let myType: { str: string; other: number; };", "other", "other");
});

it("should get the property by function", () => {
doTest("let myType: { str: string; other: number; };", p => p.getName() === "other", "other");
});

it("should throw when not exists", () => {
doTest("let myType: { str: string; other: number; };", "test", undefined);
});
});

describe(nameof<Type>(t => t.getProperty), () => {
function doTest(text: string, nameOrFindFunction: string | ((declaration: Symbol) => boolean), expected: string | undefined) {
const { firstType } = getTypeFromText(text);
const prop = firstType.getProperty(nameOrFindFunction);
if (expected == null)
expect(prop).to.be.undefined;
else
expect(prop!.getName()).to.equal(expected);
}

it("should get the property by name", () => {
const { firstType } = getTypeFromText("let myType: { str: string; other: number; };");
const prop = firstType.getProperty("other")!;
expect(prop.getName()).to.equal("other");
doTest("let myType: { str: string; other: number; };", "other", "other");
});

it("should get the property by function", () => {
const { firstType } = getTypeFromText("let myType: { str: string; other: number; };");
const prop = firstType.getProperty(p => p.getName() === "other")!;
expect(prop.getName()).to.equal("other");
doTest("let myType: { str: string; other: number; };", p => p.getName() === "other", "other");
});

it("should return undefined when not exists", () => {
doTest("let myType: { str: string; other: number; };", "test", undefined);
});
});

Expand Down

0 comments on commit c929c6c

Please sign in to comment.