Correct way of getting type for a variable declaration in a typescript AST?

非 Y 不嫁゛ 提交于 2021-02-07 19:46:07

问题


Took a look at the declarationEmitter and for variable declarations, it has the function #emitVariableDeclaration which eventually calls #writeTypeOfDeclaration. This code does what is says---it takes a variable declaration and prints the variable and its type---this is exactly what I want to do.

The problem is that when I replicate this code, the VariableDeclaration node has no symbol property...and thus, the type is always "any". Is there a missing step to initialize "symbols"?

//sample input filecontents
export const foo = '123'

//mycode.js
const ast = ts.createSourceFile(filename, filecontents, ts.ScriptTarget.ES6, true))
const program = ts.createProgram([filename], {});
const typeChecker = program.getDiagnosticsProducingTypeChecker()
const emitResolver = typeChecker.getEmitResolver(filename)
// variableDeclarationNode --- can be obtained using ts.forEachChild and finding node with kind === ts.SyntaxKind.VariableDeclaration
// writer --- an object implementing the SymbolWriter interface that just concatenates to a result string
emitResolver.writeTypeOfDeclaration(variableDeclarationNode, undefined, undefined, writer)

//declarationEmitter.ts
function writeTypeOfDeclaration(
      declaration: AccessorDeclaration | VariableLikeDeclaration, 
      type: TypeNode, 
      getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) {
   //...
   resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
}

//`checker.ts`
function writeTypeOfDeclaration(
    declaration: AccessorDeclaration | VariableLikeDeclaration,       
    enclosingDeclaration: Node, 
    flags: TypeFormatFlags, 
    writer: SymbolWriter) {

    // Get type of the symbol if this is the valid symbol otherwise get type at location
    const symbol = getSymbolOfNode(declaration);
    const type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
        ? getTypeOfSymbol(symbol)
        : unknownType;

    // ....
}

function getMergedSymbol(symbol: Symbol): Symbol {
    let merged: Symbol;
    return symbol && symbol.mergeId && (merged = mergedSymbols[symbol.mergeId]) ? merged : symbol;
}

function getSymbolOfNode(node: Node): Symbol {
    return getMergedSymbol(node.symbol);
}

回答1:


It turns out I was using the wrong AST. In the question, I'm using the AST that doesn't have type. You can get the AST with type injected with the program. The (more) correct solution is:

const program = ts.createProgram(filename, {target: ts.ScriptTarget.ES6, module: ts.ModuleKind.ES6});
const typechecker = program.getDiagnosticsProducingTypeChecker()
const emitResolver = typeChecker.getEmitResolver(filename)))

// THIS IS HOW TO GET AN AST WITH TYPE (Yes, it's called a "SourceFile")
const ast = program.getSourceFile(filename)

// variableDeclarationNode --- can be obtained using ts.forEachChild and finding node with kind === ts.SyntaxKind.VariableDeclaration
// writer --- an object implementing the SymbolWriter interface that just concatenates to a result string
emitResolver.writeTypeOfDeclaration(variableDeclarationNode, undefined, undefined, writer)



回答2:


Is there a missing step to initialize "symbols"?

This is the job of the binder.

Some docs : https://basarat.gitbooks.io/typescript/content/docs/compiler/binder.html



来源:https://stackoverflow.com/questions/34847471/correct-way-of-getting-type-for-a-variable-declaration-in-a-typescript-ast

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!