Skip to content

Instantly share code, notes, and snippets.

David Sherret dsherret

Block or report user

Report or block dsherret

Hide content and notifications from this user.

Learn more about blocking users

Contact Support about this user’s behavior.

Learn more about reporting abuse

Report abuse
View GitHub Profile
dsherret / transform-to-relative-module-specifiers.ts
Last active Jan 12, 2019
Converts all module specifiers within a directory to relative paths.
View transform-to-relative-module-specifiers.ts
// untested...
import { Project, SyntaxKind } from "ts-simple-ast";
const project = new Project({ tsConfigFilePath: "tsconfig.json" });
const srcDir = project.getDirectoryOrThrow("./src");
for (const sourceFile of project.getSourceFiles().filter(s => srcDir.isAncestorOf(s))) {
for (const dec of [...sourceFile.getImportDeclarations(), ...sourceFile.getExportDeclarations()]) {
const moduleSpecifierSourceFile = dec.getModuleSpecifierSourceFile();
if (moduleSpecifierSourceFile == null || !srcDir.isAncestorOf(moduleSpecifierSourceFile))
dsherret / prefix-internal-class-members.ts
Last active Jan 12, 2019
Programmatic refactor to prefix all private, protected, and internal class members with an underscore.
View prefix-internal-class-members.ts
// This script will look at all the exported class declarations from the main entrypoint of a library
// and ensure all private, protected, and @internal members are prefixed with an underscore.
import { Project, Node, SyntaxKind, TypeGuards, Scope, ClassMemberTypes, ParameterDeclaration } from "ts-simple-ast";
const project = new Project({ tsConfigFilePath: "tsconfig.json" });
const sourceFiles = project.getSourceFiles();
for (const file of sourceFiles)
for (const classDec of file.getDescendantsOfKind(SyntaxKind.ClassDeclaration))
for (const member of classDec.getMembers())
dsherret / find-unused-exports.ts
Last active May 8, 2019
Searches files for any exported declarations that aren't used in other files.
View find-unused-exports.ts
// this could be improved... (ex. ignore interfaces/type aliases that describe a parameter type in the same file)
import { Project, TypeGuards, Node } from "ts-morph";
const project = new Project({ tsConfigFilePath: "tsconfig.json" });
for (const file of project.getSourceFiles()) {
file.forEachChild(child => {
if (TypeGuards.isVariableStatement(child)) {
if (isExported(child))
dsherret / ensure-public-api-has-tests.ts
Last active Sep 24, 2018
Analyzes code to find missing tests.
View ensure-public-api-has-tests.ts
* Ensure Public API Has Tests
* ---------------------------
* This demonstrates analyzing code to find methods and properties from the public
* api that don't appear in the tests.
* This is a very basic implementation... a better implementation would examine more
* aspects of the code (ex. are the return values properly checked?) and report
* statistics about the tests that possibly indicate how they could be improved (ex.
* "this test has a lot of overlap with these other tests"). The goal would be to
View tsquery-with-ts-simple-ast.ts
import { tsquery } from "@phenomnomnominal/tsquery";
import { Node } from "ts-simple-ast";
export function query(node: Node, query: string) {
return tsquery(node.compilerNode, query)
.map(n => (node as any)._getNodeFromCompilerNode(n) as Node);
dsherret / WeakCache.ts
Last active Sep 27, 2018
A weak cache with support for ES5.
View WeakCache.ts
export class WeakCache<T extends object, U> {
private readonly cacheItems: WeakDictionary<T, U>;
constructor() {
if (typeof WeakMap !== "undefined")
this.cacheItems = new WeakMap<T, U>();
this.cacheItems = new Es5WeakMap();
View EnumEx.ts
// only works with number enums...
class EnumEx {
private constructor() {
static getMembersCount(e: any) {
return EnumEx.getNames(e).length;
static getMemberValue(e: any, memberName: string) {
View ThrottledQueue.ts
export class ThrottledQueue {
private isThrottling = false;
private items: (() => void)[] = [];
constructor(private duration: number) {
run(item: () => void) {
View noDuplicateImportsFromSameFileRule.ts
import * as ts from "typescript";
import * as Lint from "tslint/lib/lint";
export class Rule extends Lint.Rules.AbstractRule {
static FAILURE_STRING = "duplicate imports from same file forbidden";
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new NoImportsWalker(sourceFile, this.getOptions()));
View memoize-decorator.ts
* Caches the return value of get accessors and methods.
* Notes:
* - Doesn't really make sense to put this on a method with parameters.
* - Creates an obscure non-enumerable property on the instance to store the memoized value.
* - Could use a WeakMap, but this way has support in old environments.
export function Memoize(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<any>) {
if (descriptor.value != null) {
You can’t perform that action at this time.