Repository navigation
Description
🔍 Search Terms
"ast json"
"ast output"
"abstract syntax tree output"
✅ Viability Checklist
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
⭐ Suggestion
I am NOT a TypeScript or JavaScript developer but need to generate other languages from structures held in these languages. This is the crux of the what follows though it may not use the correct vocabulary.
Allow a TypeScript or JavaScript file to be output as a JSON abstract syntax tree directly from tsc. This would likely consist of a correctly coded version of the below script.
Note that this issue does not require the output format to be frozen, as the output from the command could itself be defined to be correct. While users of this functionality (such as myself) may have to change our downstream scripts, we would at least benefit from a known correct producer of AST JSON output.
#!/usr/bin/env node
// Original source from https://github.com/seachicken/tsparser
"use strict";
const ts = require("typescript");
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value
const getCircularReplacer = function () {
const seen = new WeakSet();
return function (key, value) {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
};
const sourceFiles = process.argv.slice(2).map((input) => {
const program = ts.createProgram([input], { allowJs: true });
const sourceFile = program.getSourceFile(input);
function parse(node) {
// https://github.com/microsoft/TypeScript/blob/1294ee8c1f37c8bf214db67e180edb3220a52236/src/compiler/types.ts#L21
node.kindName = ts.SyntaxKind[node.kind];
node.start = node.getStart(sourceFile);
ts.forEachChild(node, parse);
}
ts.forEachChild(sourceFile, parse);
return sourceFile;
});
try {
process.stdout.write(JSON.stringify(sourceFiles, getCircularReplacer()));
} catch (error) {
process.stdout.write("\n");
process.stderr.write("".concat(error, "\n"));
}📃 Motivating Example
I have a number of structure definitions held in TypeScript which need to be shared in other languages such as Kotlin and Go. As is often the case in these situations I have expertise only in the destination language but am required to accurately parse the source language.
💻 Use Cases
- What do you want to use this for?
- Exporting Typescrypt to other languages, either computational such as Swift, or a definition language such as OpenAPI.
- What shortcomings exist with current approaches?
- The user often does not have the expertise to find and code the correct TypeScript solution.
- What workarounds are you using in the meantime?
- The above script (which may or may not be correct)
Activity
MartinJohns commentedon Feb 24, 2025
IMO this falls under non-goal 4 of the Language Design Goals:
jjrscott commentedon Feb 24, 2025
Thanks Martin Johns (@MartinJohns) though I'd argue it falls under the "instead" part of non-goal 4:
In this case the "external tool" in question is written in an entirely different language / build system.
RyanCavanaugh commentedon Feb 24, 2025
Internals like this aren't something we want to prioritize emitting from tsc. There's nothing particularly meaningful you can do with this, and many other parsers already exist.
jakebailey commentedon Feb 24, 2025
FWIW you can already do this today with alternative TypeScript parsers which spit out estree-compatible objects. For example,
@typescript-eslint/parserconverts our AST into one readable by ESLint, and that same library is used byprettierto format code. oxc has similar support (though a different tree than ts-eslint).jjrscott commentedon Feb 24, 2025
Ryan Cavanaugh (@RyanCavanaugh) I'm using the above code to generate cross platform types from existing TypeScript code. Given the web side of our team are using
tscto compile their code it made sense to use this project rather than any other. As a non-TypeScript developer I would need to significally upskill to be able to advocate another external dependancy within my group.I appreciate that this might not be important within the TypeScript community but it really helps us "neighbours" use TypeScript code. The above code took me a few days to find and pin down as I didn't even know what I was looking for beyond that I needed the same out on the CLI that I was seeing on https://astexplorer.net.
Given TypeScript's frankly astonishing type description abilities, it would be a shame for other external parties to miss out on what I eventually found to be possible (I'm still not sure the above script is "correct").
typescript-bot commentedon Feb 28, 2025
This issue has been marked as "Out of Scope" and has seen no recent activity. It has been automatically closed for house-keeping purposes.
jjrscott commentedon Feb 28, 2025
This is disappointing. I believed this request would fall clearly into the goals of:
As a non-TypeScript programmer, utilising TypeScript in a larger project requires signficant upskilling. Hopefully, others treading the same path will at least be able to use the above code to make progress with their own requirements.
MartinJohns commentedon Feb 28, 2025
You misunderstand what this part means. It doesn't mean the TypeScript tooling will support all kinds of use cases that may be needed by third-party tooling. It means the compiler API is open and usable by third-parties, so they can write tools utilizing the compiler API to fulfill their use cases (one example being your script).
jjrscott commentedon Mar 2, 2025
Martin Johns (@MartinJohns) While from an internal perspective the compiler API may hook of choice, externally
tscis the TypeScript project. One is forced to learn oftscin the first few minutes, discovering and then using the compiler API took days, even for a self professed language/compiler nerd. While external non-TypeScript programmers can write tools utilizing the compiler API to fulfill their use cases, as I did, the cost was very high.I can only advise that, in this particlar case and in my experience, the barriers to entry are too high.