Determine the data type of a variable in TypeScript by utilizing the compiler API

I am facing an issue with retrieving the type of a variable using the compiler API. Here is some background information on my situation: Since I execute everything in memory, I have had to create my own compiler host. This is necessary because the typechecker is generated from a 'program' which by default expects files to be written to disk.

In the code sample below, I attempt to determine the types of "input" and "el". I anticipate the output to be "number[]" and "number", respectively. This matches what I would see if I were to hover over them in VSCode.

However, the output that I receive is either "{}" or "any".

I am certain that I am doing something incorrectly or overlooking something, but I cannot seem to identify what it is.

Warm regards, Ike

const code: string = `let input: number[] = [1, 2, 3];
for (let el of input) {
    let x = el * 3;
    if (el > 1) {
        output.push(el);
    }
}`;

const host: ts.CompilerHost = {
  getSourceFile(fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void): ts.SourceFile {
    console.log("getSourceFile", fileName);
    if (fileName === "test.ts") {
        return ts.createSourceFile(fileName, code, languageVersion);
    }
    if (onError) {
        onError("not found");
    }
    // tsc's declarations don't support strict null checks
    return null as any as ts.SourceFile;
  },
  getDefaultLibFileName: () => "", // "lib.d.ts",
  writeFile: (_fileName, _content) => { },
  getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
  getCanonicalFileName: fileName => ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
  getNewLine: () => ts.sys.newLine,
  useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
  fileExists: (fileName: string) => fileName === "test.ts",
  readFile(fileName: string): string {
    if (fileName === "test.ts") {
      return code;
    }
    return null as any as string;
  },
  resolveModuleNames(_moduleNames: string[], _containingFile: string): ts.ResolvedModule[] {
    throw new Error("unsupported");
  },
  getDirectories(_path: string): string[] {
    throw new Error("unsupported");
  }
};


const program: ts.Program = ts.createProgram(["test.ts"], {allowJs: true}, host);
const checker: ts.TypeChecker = program.getTypeChecker();
const forofke: ts.ForOfStatement = program.getSourceFiles()[0].statements[1];
const stat = forofke.expression;
const type1: ts.Type = checker.getTypeAtLocation(stat);
console.log(checker.typeToString(type1));
const sym: ts.Symbol = checker.getSymbolAtLocation(stat);
const type2: ts.Type = checker.getDeclaredTypeOfSymbol(sym);
console.log(checker.typeToString(type2));
const type3: ts.Type = checker.getTypeOfSymbolAtLocation(sym, stat);
console.log(checker.typeToString(type3));
const type4: ts.Type = checker.getTypeOfSymbolAtLocation(sym, sym.valueDeclaration);
console.log(checker.typeToString(type4));

const stat2 = (<ts.VariableDeclarationList>forofke.initializer).declarations[0].name;
const type12: ts.Type = checker.getTypeAtLocation(stat2);
console.log(checker.typeToString(type12));
const sym2: ts.Symbol = checker.getSymbolAtLocation(stat2);
const type22: ts.Type = checker.getDeclaredTypeOfSymbol(sym2);
console.log(checker.typeToString(type22));
const type32: ts.Type = checker.getTypeOfSymbolAtLocation(sym2, stat2);
console.log(checker.typeToString(type32));
const type42: ts.Type = checker.getTypeOfSymbolAtLocation(sym2, sym2.valueDeclaration);
console.log(checker.typeToString(type42));

Answer №1

After thoroughly assessing a 'program' loaded from disk and comparing it to the one in memory, I observed that there are 2 source files present in 'program.getSourceFiles()' when fetched from disk. Interestingly, the second file is lib.d.ts.

Having made some adjustments to my sample, I now see the output aligning with my expectations.

  getSourceFile(fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void): ts.SourceFile {
    console.log("Obtaining Source File", fileName);
    if (fileName === "test.ts") {
        return ts.createSourceFile(fileName, code, languageVersion);
    }
    if (fileName === "lib.d.ts") {
        return ts.createSourceFile(fileName, /*READ the file from disk*/, languageVersion);
    }
    if (onError) {
        onError("File not found");
    }
    // TypeScript compiler declarations do not fully embrace strict null checks
    return null as any as ts.SourceFile;
  },
  getDefaultLibFileName: () => "lib.d.ts",

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The specified property 'XYZ' is not found in the type 'Readonly<{ children?: ReactNode; }> & Readonly<{}>'

Whenever I try to access .props in RecipeList.js and Recipe.js, a syntax error occurs. Below is the code snippet for Recipe.js: import React, {Component} from 'react'; import "./Recipe.css"; class Recipe extends Component { // pr ...

Toggle the Visibility of your Password

I am currently working on implementing a TypeScript function in my webpage to enable the toggling of password visibility using an icon. The desired functionality is as follows: when a button (in this case, a clickable icon) is pressed, the icon should chan ...

Exploring the use of MediaSource for seamless audio playback

Currently working on integrating an audio player into my Angular web application by following a tutorial from Google Developers and seeking guidance from a thread on Can't seek video when playing from MediaSource. The unique aspect of my implementati ...

React TypeScript: The properties of 'X' are not compatible. 'Y' cannot be assigned to 'Z' type

I am currently working on a React-TypeScript application, specifically creating a component for inputting credit card numbers. My goal is to have the FontAwesome icon inside the input update to reflect the brand image as the user enters their credit card n ...

Errors TS2585 and TS2304 encountered during compilation of TypeScript file using Axios

What steps should I take to fix the errors that arise when attempting to compile my TypeScript code using tsc index.ts? node_modules/axios/index.d.ts:75:3 - error TS1165: In an ambient context, a computed property name must reference an expression of lite ...

Issue with ng-multiselect-dropdown where clearing selected items programmatically does not visually work as expected

Utilizing the ng-multiselect-dropdown, I have encountered an issue where deselecting an option within the object itself clears the selected items visually and in the variable array. However, when programmatically clearing the selectedItems, the variable a ...

*ngFor is not rendering

I understand that this question is frequently asked, but the usual solutions don't seem to be effective in this case. Here is my code snippet: export class CourseReviewFormComponent implements OnInit { form: FormGroup questionnaire: string[] = [] ...

Is there a way to update a JSON within a function in the context of API programming with Angular?

Here is the JSON data I am working with: .json "type": [ { "id": 2, "secondid": "1", "name": "f", "positionX": 0, "positionY": 0 }] Alongside thi ...

How do I correctly specify the parameter type of a function when passing a React functional component as an argument in TypeScript?

I am facing an issue with type declaration for function parameters. See the code snippet below, const FunctionalComponent = ({propA,propB}: FunctionalComponentProps): JSX.Element => { return } Now, I need to pass the FunctionalComponent as a parame ...

Angular Lifecycle Hook - Data loading initializes after the view initialization is complete

In my component, I have loaded a firestore document and converted it into a plain js object within the constructor. However, when trying to access the field values in the template, there is a slight delay in loading them. This results in an error being dis ...

What could be causing the error in the console when I try to declare datetime in Ionic?

I am just starting out with Ionic and Angular, but I seem to have hit a roadblock. The compiler is throwing an error that says: node_modules_ionic_core_dist_esm_ion-app_8_entry_js.js:2 TypeError: Cannot destructure property 'month' of '(0 , ...

Users are reporting a problem with the PrimeNG confirmation dialog where it becomes unresponsive and locks up the screen

Previously functioning code seems to have been affected by an update to PrimeNG. The confirmation dialog that was once usable is now hidden behind a gray click-mask, rendering everything on the screen unclickable: The HTML structure for these two dialogs ...

Exploring Array Iteration in a subscribe and ngOnInit Function

I'm facing a challenge where I need to iterate through an .subscribe() method placed inside an ngOnInit() method: ngOnInit() { this.service.getEmployees().subscribe( (listBooks) => { this.books = listBooks var events: C ...

Running out of memory due to inefficient mark-compacting processes nearing the heap limit in Angular 8 allocation

A significant portion of the modules are built, with only one active in progress. The process is located at ...\src\index.js??extracted!D:\Clients\app\node_modules\sass-loader\lib\loader.js??ref--15-3!D:\src&bso ...

A function in Typescript designed to take in two objects that possess identical keys

I am looking to define a function that takes two parameters, each being an object. These objects have the same keys, but the data types of the values under those keys should be different (yet the same within each object). I attempted to achieve this using ...

Can you explain the significance of using curly braces in an import statement?

The TypeScript handbook has a section on Shorthand Ambient Modules, where an import statement is shown as: import x, {y} from "hot-new-module"; It doesn't explain why y is in curly braces in the above statement. If both x and y were inside the brace ...

When converting to a React Functional Component using Typescript, an error occurred: The property 'forceUpdateHandler' could not be found on the type 'MutableRefObject<Spinner | null>'

Looking to convert the App component in this CodePen into a Functional component using Typescript. Encountering an error when attempting to run it: ERROR in src/App.tsx:13:14 TS2339: Property 'forceUpdateHandler' does not exist on type 'Mu ...

Bringing in information from a TypeScript document

I'm having trouble importing an object from one TypeScript file to another. Here is the code I am working with: import mongoose from "mongoose"; import Note from './models/notes'; import User from './models/users'; import ...

How to pass a String Array to a String literal in JavaScript

I need to pass an array of string values to a string literal in the following way Code : var arr = ['1','2556','3','4','5']; ... ... var output = ` <scr`+`ipt> window.stringArray = [`+ arr +`] & ...

When a URL is triggered via a browser notification in Angular 2, the target component ceases to function properly

Whenever I access a URL by clicking on a browser notification, the functionality of the page seems to stop working. To demonstrate this issue, I have a small project available here: https://github.com/bdwbdv/quickstart Expected behavior: after starting t ...