yantrab
yantrab

Reputation: 2662

typescript compiler api - How to detect if property type is enum or object

I have to know each property declaration node, if is enum or another object.

so i get the type reference :

 const typeReferance = (arrayType as any).typeName

But i don't have any idea how to detect if is enum, or object.

Models:

enum Color { Red, Green, Blue }
class SomeObject {
    string: string;
}
class Model {
    color:Color;
}

The visitor:

if (node.kind === ts.SyntaxKind.PropertyDeclaration) {
  ???
}

Upvotes: 2

Views: 1491

Answers (2)

Astra Bear
Astra Bear

Reputation: 2738

I have tried the "kind" attribute with success eg

`   function visit(node: ts.Node) {
        if (!domain) {
            return;
        }

        if (node.kind === ts.SyntaxKind.ClassDeclaration) {
            //  console.log("Interface ignore");
            domain.isClass = true;
        }
        if (node.kind === ts.SyntaxKind.EnumDeclaration) {
            //  console.log("Interface ignore");
            domain.isEnum = true;
        }

        if (node.kind === ts.SyntaxKind.InterfaceDeclaration) {
            //  console.log("Interface ignore");
            domain.isInterface = true;
            return;
        }
        if (node.kind === ts.SyntaxKind.ImportDeclaration) {
            //console.log("Import Ignore");
            //output = null;
            return;
        }
        if (node.kind === ts.SyntaxKind.DefaultKeyword) {
            //console.log("DEFAULT");
            return;
        }
        if (node.kind === ts.SyntaxKind.ExportKeyword) {
            exportStatementFound = true;
            //console.log("EXPORT");
            return;
        }


        if (ts.isClassDeclaration(node) && node.name) {
           //do something
        }
  }`

Upvotes: 0

David Sherret
David Sherret

Reputation: 106640

I've found checking the type flag for TypeFlags.Enum is not reliable (maybe a bug in the compiler api, but I've been kind of lazy to look into it). What I do is get the ts.Type's symbol and check if its value declaration is an enum declaration.

This is untested, but should give you the basic idea:

function isEnumType(type: ts.Type) {
    // if for some reason this returns true...
    if (hasFlag(type.flags, ts.TypeFlags.Enum))
        return true;

    // it's not an enum type if it's an enum literal type
    if (hasFlag(type.flags, ts.TypeFlags.EnumLiteral) && !type.isUnion())
        return false;

    // get the symbol and check if its value declaration is an enum declaration
    const symbol = type.getSymbol();
    if (symbol == null)
        return false;

    const { valueDeclaration } = symbol;
    return valueDeclaration != null && valueDeclaration.kind === ts.SyntaxKind.EnumDeclaration;
}

function hasFlag(type: ts.Type, flag: ts.TypeFlags) {
    return (type.flags & flag) === flag;
}

Checking if it's an object is a little easier...

function isObjectType(type: ts.Type) {
    return hasFlag(type.flags, ts.TypeFlags.Object);
}

By the way, in case you are not familiar with it, the type of a node can be retrieved from the type checker:

const type = typeChecker.getTypeAtLocation(typeReference);

Upvotes: 1

Related Questions