Skip to content Skip to sidebar Skip to footer

Typescript Source Parse: Get Interface Related To Certain React Class

I want to get props from React class declared in interface related to this class. For example I have this kind of code interface SomeProps { text: string; label?: string; }

Solution 1:

Sure you can use the compiler API to achieve this.

// sample.ts
import * as React from 'react'

interface SomeProps {
    text: string;
    label?: string;
}

class SomeClass extends React.Component<SomeProps> {

}

// getProps.ts
import * as ts from "typescript";


function isReactComponent (baseType: ts.Type) {
    if (baseType == null) return false;

    let baseTypeSymbol = baseType.getSymbol();
    if (baseTypeSymbol == null) return false;
    // Base type is named Component
    if (baseTypeSymbol.getName() !== "Component") return false;

    var declarations = baseTypeSymbol.declarations;
    if (declarations == null) return false;

    // With the declartion beeing located inside the react module
    return declarations.some(r => r.getSourceFile().fileName.indexOf("node_modules/@types/react") !== -1);
}


function compile(fileNames: string[], options: ts.CompilerOptions): void {
    let program = ts.createProgram(fileNames, options);
    let sample = program.getSourceFile("sample.ts");
    if (sample == null) return;

    let checker = program.getTypeChecker();
    // Get declarations inside the file
    let list = sample.getChildAt(0) as ts.SyntaxList;

    for (let i = 0, n = list.getChildCount(); i < n; i++) {
        let clazz = list.getChildAt(i);
        // if the child is a class 
        if (!ts.isClassDeclaration(clazz)) continue;

        // Get the heritage classes of the class
        let heritageClauses = clazz.heritageClauses;
        if (heritageClauses == null) continue;

        // Iterate the heritage clauses
        for (const heritageClause of heritageClauses) {
            // Only take the extends clauses
            if (heritageClause.token !== ts.SyntaxKind.ExtendsKeyword) continue;

            // Get the type of the extends 
            let extendsType = heritageClause.types[0];
            // If the base type is React.Component
            if (isReactComponent(checker.getTypeFromTypeNode(extendsType))) {
                // Get the type argument of the expression 
                var propType = extendsType.typeArguments![0];

                let type = checker.getTypeFromTypeNode(propType);
                console.log(`The name of props is ${type.getSymbol()!.getName()}`);
                var props = type.getProperties();
                for (let prop of props) {
                    console.log(`  Contains prop: ${prop.getName()}`);
                }
            }
        }

    }
}

compile(["sample.ts"], {}); 

Post a Comment for "Typescript Source Parse: Get Interface Related To Certain React Class"