Renaming TypeScript interfaces with ts-morph
ts-morph is a tool to write codemods for TypeScript — programs that modify TypeScript code.
Here’s how I removed the I
prefixes of all interfaces in a project: IDog
becomes Dog
.
- Create a file with the codemod, src/remove-prefixes.ts:
import { Project } from 'ts-morph';
// Initialize a project with our tsconfig file
const project = new Project({
tsConfigFilePath: 'tsconfig.json'
});
// Get all project files
const sourceFiles = project.getSourceFiles();
sourceFiles.forEach(sourceFile => {
console.log('👉', sourceFile.getBaseName());
// Get all interfaces in a file
const interfaces = sourceFile.getInterfaces();
interfaces.forEach(i => {
// IDog → Dog
const name = i.getName();
const nextName = name.replace(/^I([A-Z])/, '$1');
if (name === nextName) {
return;
}
// Rename interface
console.log(name, '->', nextName);
i.rename(nextName, {
renameInComments: true,
renameInStrings: true
});
});
console.log();
});
// Save all changed files
project.saveSync();
- Install dependencies:
npm install --save-dev ts-morph
- Run the codemod:
ts-node --compiler-options '{"module": "commonjs"}' src/remove-prefixes.ts
Note We need to override compiler options here because our project is using webpack and ECMAScript modules aren’t transpiled, which is required for Node.js.
#Caveats
This codemod doesn’t do anything with naming conflict. For example, if we already have a Dog
component or class and we’re importing the IDog
interface into the same file, we’ll have a naming conflict: both, the component and the interface will be called Dog
.