Skip to content

Instantly share code, notes, and snippets.

dsherret / getDeepMutableClone.ts
Last active December 11, 2019 21:13
Cloning a TypeScript compiler API node.
// one way...
function getDeepMutableClone<T extends ts.Node>(node: T): T {
return ts.transform(node, [
context => node => deepCloneWithContext(node, context)
function deepCloneWithContext<T extends ts.Node>(
node: T,
context: ts.TransformationContext
dsherret / proxiedClone.ts
Last active November 23, 2019 05:03
Cloning an immutable object via a proxy.
// I wrote this to test if it would be faster for my scenario and it wasn't... it was much much slower.
// So I'm throwing it away here on a gist. Perhaps someone would still find it useful.
* Mimicks the behaviour of cloning via a proxy for when the underlying object
* will never change, but the clone might.
* @param originalObject - Object to create a proxied clone of.
export function proxiedClone<T extends object>(originalObject: T): T {
const proxies = new Map<object, object>();
// Adapted from:
using System;
using System.Diagnostics;
namespace CommonShared.Audio
public class MelFrequencyBinner
private const int _melFiltersCount = Constants.MEL_FILTERS_COUNT;
dsherret / transform-to-relative-module-specifiers.ts
Last active January 12, 2019 00:54
Converts all module specifiers within a directory to relative paths.
// 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 January 12, 2019 00:54
Programmatic refactor to prefix all private, protected, and internal class members with an underscore.
// 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 December 22, 2023 00:03
Searches files for any exported declarations that aren't used in other files.
// 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 September 24, 2018 18:02
Analyzes code to find missing tests.
* 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
import { tsquery } from "@phenomnomnominal/tsquery";
import { Node } from "ts-morph";
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 September 27, 2018 23:53
A weak cache with support for ES5.
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();
// only works with number enums...
class EnumEx {
private constructor() {
static getMembersCount(e: any) {
return EnumEx.getNames(e).length;
static getMemberValue(e: any, memberName: string) {