Last active
February 6, 2025 13:07
-
-
Save betafcc/3fde408c76c68bc8e9f1d0f4a0dd5cc5 to your computer and use it in GitHub Desktop.
Expand type aliases from a typescript file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { readFileSync } from 'node:fs' | |
import { resolve } from 'node:path' | |
import JSON5 from 'json5' | |
import ts from 'typescript' | |
import * as prettier from 'prettier' | |
/** | |
* reveal all top level `type` declarations from a file | |
*/ | |
export const reveal = async (sourcePath: string) => { | |
const program = ts.createProgram([sourcePath], getConfig()) | |
const checker = program.getTypeChecker() | |
const revealed = program | |
.getSourceFile(sourcePath)! | |
.getChildren() | |
.flatMap(c => c.getChildren()) | |
.filter(ts.isTypeAliasDeclaration) | |
.map(c => getFullDeclarationText(checker, c)) | |
.join('\n\n') | |
return await prettier.format(revealed, { | |
parser: 'typescript', | |
semi: false, | |
}) | |
} | |
const getFullDeclarationText = ( | |
checker: ts.TypeChecker, | |
c: ts.TypeAliasDeclaration, | |
) => getTypeDeclarationText(c) + typeToString(checker, c) | |
const typeToString = (checker: ts.TypeChecker, c: ts.TypeAliasDeclaration) => | |
checker.typeToString( | |
checker.getTypeAtLocation(c.type), | |
undefined, | |
ts.TypeFormatFlags.InTypeAlias | ts.TypeFormatFlags.NoTruncation, | |
) | |
const getTypeDeclarationText = (c: ts.TypeAliasDeclaration) => | |
c.getText().slice(0, c.getText().lastIndexOf(c.type.getText())) | |
const getConfig = () => { | |
const configFile = ts.findConfigFile( | |
'.', | |
ts.sys.fileExists, | |
'tsconfig.json', | |
) as string | |
// return JSON5.parse(readFileSync(configFile, { encoding: 'utf-8' })) | |
return JSON5.parse(readFileSync(configFile) as any) | |
} | |
/** | |
* I usually put this file in a scratch folder in the project and run as | |
* | |
* ```bash | |
* npx ts-node-dev --respawn -T --compiler-options '{"module": "commonjs"}' ./scratch/reveal.ts ./test.ts | |
* ``` | |
* | |
* In order for this to rerun when the sourcePath file changes, | |
* a good trick is to `import` it here, so ts-node-dev will know | |
* to rerun this, also is better to run `reveal` only after | |
* the file is fully imported, I had problems with reveal getting | |
* previous source if not | |
*/ | |
const sourcePath = resolve(process.argv.at(-1)!) | |
import(sourcePath).then(() => reveal(sourcePath)).then(console.log) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment