Although I am familiar with ts-ast-viewer, I am unsure of how they extract a list of elements from the union.
I have experimented with different existing solutions, such as this one, but it appears that most of them are outdated. Some ts.[methods]
have been deprecated.
Below is the initial code I used to debug the compiler API:
import * as ts from "typescript";
const code = "type Foo = 'one'|'two'|'three'";
const sourceFile = ts.createSourceFile(
"foo.ts",
code,
ts.ScriptTarget.Latest,
true
);
function print(node: ts.Node, name: string) {
console.log({ node });
}
print(sourceFile, "Foo");
I have seen an example on the TS wiki and created a modified version:
//@ts-ignore
import * as ts from "typescript";
const code = "type Foo = 'one'|'two'|'three'";
const sourceFile = ts.createSourceFile(
"foo.ts",
code,
ts.ScriptTarget.Latest,
true
);
function extract(identifiers: string[]): void {
//@ts-ignore
const unfoundNodes = [];
//@ts-ignore
const foundNodes = [];
//@ts-ignore
ts.forEachChild(sourceFile, (node) => {
let name = "";
//@ts-ignore
if (ts.isFunctionDeclaration(node)) {
//@ts-ignore
name = node.name.text;
//@ts-ignore
node.body = undefined;
//@ts-ignore
} else if (ts.isVariableStatement(node)) {
//@ts-ignore
name = node.declarationList.declarations[0].name.getText(sourceFile);
//@ts-ignore
} else if (ts.isInterfaceDeclaration(node)) {
name = node.name.text;
}
//@ts-ignore
const container = identifiers.includes(name) ? foundNodes : unfoundNodes;
//@ts-ignore
container.push([name, node]);
});
//@ts-ignore
return (unfoundNodes[0][1] as any).type.types.map(
(elem: any) => elem.literal.text
);
}
// Run the extract function with the script's arguments
console.log(extract(["Foo"]));
While this setup worked for
"type Foo = 'one'|'two'|'three'"
, it failed for "type Foo = keyof Array<any>"
.
I am aware that my current version is incorrect.
I also attempted to use another example, but it appears that forEachDescendant
does not exist for node
.
Any suggestions on how to create a function to retrieve an array of elements from a union?
Here's the function structure I am aiming for:
import * as ts from "typescript";
const sourceCode = "type Foo = keyof Array<number>";
union(sourceCode, "Foo") // ["forEach", "reduce", "map" ...]
This is crucial for my debugging process.