Skip to content

Instantly share code, notes, and snippets.

@dsherret
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))
child.getDeclarations().forEach(checkNode);
@dsherret
dsherret / Using.ts
Last active October 26, 2023 13:30
Typescript Disposable (using statement)
// NOTE: This is now rolled up in a package and supports more scenarios: https://github.com/dsherret/using-statement
interface IDisposable {
dispose();
}
function using<T extends IDisposable>(resource: T, func: (resource: T) => void) {
try {
func(resource);
} finally {
/**
* 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) {
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);
}
// Adapted from: https://github.com/Sciss/SpeechRecognitionHMM/blob/master/src/main/java/org/ioe/tprsa/audio/feature/MFCC.java
using System;
using System.Diagnostics;
namespace CommonShared.Audio
{
public class MelFrequencyBinner
{
private const int _melFiltersCount = Constants.MEL_FILTERS_COUNT;
@dsherret
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)
]).transformed[0];
function deepCloneWithContext<T extends ts.Node>(
node: T,
context: ts.TransformationContext
@dsherret
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>();
@dsherret
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
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
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>();
else
this.cacheItems = new Es5WeakMap();
}