Gaetan Le Gac
Gaetan Le Gac

Reputation: 141

Typescript Compiler API: Generate the full properties arborescence of a Type Identifier

Given a type Identifier, I'm searching for a way to generate the full arborescence of an object type AST. By example, if I have:

File1.ts

type Content = {
    title: string,
    image: string,
    dims: number[]
}

File2.ts

type BlogPost = Pick<Content, 'title'|'image'>

type User {
    name: string,
    email: string,
    news: BlogPost[]
}

File3.ts

const test: User = { ... };

My code must be able to deduce, from the user identifier, a list like this one:

name
email
news.title
news.image

I experimented several things by using checker.getTypeAtLocation, iterating across each property one by one, find the right symbol, and try to deduce properties' names.

But I think (hope) this method is too much to accomplish such simple things because I have to handle, in addition to object types, every possibility of types for the properties: Picks, Excludes, Array, Omit, KeyOf, ...

All I want is the list of properties of the final complete form of a type.

So my question is:

Does the Typescript Compiler API provide tools to help me in my quest? By example, given a type like this one:

type Content = { title: string, id: number }
type Hello = Pick< Content, 'id' >

Generate a final and complete AST like this:

type Hello = {
    id: number
}

Thanks for your help

Upvotes: 5

Views: 943

Answers (1)

David Sherret
David Sherret

Reputation: 106640

All I want is the list of properties of the final complete form of a type.

Here's a fully contained example that shows how to do that:

// setup
import { Project, ts } from "@ts-morph/bootstrap";

const project = new Project();
const file = project.createSourceFile("./main.ts",
    `type Content = { title: string, id: number }; type Hello = Pick< Content, 'id' >`);
const typeChecker = project.createProgram().getTypeChecker();

// get type alias
const helloTypeAliasDec = file.statements.find(s => ts.isTypeAliasDeclaration(s)
    && s.name.getText(file) === "Hello")!;

// get the type alias' type
const type = typeChecker.getTypeAtLocation(helloTypeAliasDec);

// now loop over all its properties
for (const property of type.getProperties()) {
    const propertyType = typeChecker.getTypeOfSymbolAtLocation(property, helloTypeAliasDec);
    console.log("Name:", property.name, "Type:", typeChecker.typeToString(propertyType));
}

Outputs: Name: id Type: number

Based on this information you should be able to construct an AST, but there are a few edge cases you might run into.

Upvotes: 2

Related Questions