What is the best way to utilize the typescript module for detecting and managing typescript errors and warnings in your code?

Currently, I am experimenting with the typescript module to programmatically detect typescript errors. Below is a simplified version of what I have been working on:

var ts=require('typescript')

var file_content=`
interface Message{
  a:string
  b:number
}
var a:Message={a:'hello'}  
`
var options={
  compilerOptions:{
    module:'ES2015',
    target:'ES2015',
    inlineSourceMap:true
  },
  reportDiagnostics: true
}
const typescript_output = ts.transpileModule(file_content,options)
console.log(typescript_output.diagnostics)

The issue here is that when I execute the code using node, it consistently displays an empty array for the diagnostics, despite having a typescript error in the content stored in the file_content variable.

I would like to know: What is the correct approach to utilize the typescript module API to retrieve typescript errors?

Answer №1

transpileModule doesn't report type errors intentionally. According to information on the wiki, it is necessary to create a complete compiler in order to receive diagnostic messages. By utilizing their provided sample code, any type errors will be accurately detected:

const ts = require('typescript')

function compile (fileNames, options) {
  const program = ts.createProgram(fileNames, options)
  const emitResult = program.emit()

  const allDiagnostics = ts
    .getPreEmitDiagnostics(program)
    .concat(emitResult.diagnostics)

  allDiagnostics.forEach(diagnostic => {
    if (diagnostic.file) {
      const { line, character } = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start)
      const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')
      console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`)
    } else {
      console.log(ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'))
    }
  })

  const exitCode = emitResult.emitSkipped ? 1 : 0
  console.log(`Process exiting with code '${exitCode}'.`)
  process.exit(exitCode)
}

const options = {
  compilerOptions: {
    module: 'ES2015',
    target: 'ES2015',
    inlineSourceMap: true
  },
  reportDiagnostics: true
}

compile(process.argv.slice(2), options)

An issue that may arise is the necessity of having files on disk, which differs from your string-based approach. Should there not be a more suitable API available, using a temporary file could potentially circumvent this limitation.

Answer №2

If you're encountering issues with module resolution, consider implementing the following code snippet:

    tsconfig.compilerOptions.sourceRoot = objDir;
    const host = ts.createCompilerHost(tsconfig.compilerOptions);
    const cache = ts.createModuleResolutionCache(objDir, x => x, tsconfig.compilerOptions);

    host.resolveModuleNames = function resolveModuleNames(moduleNames: readonly string[], containingFile: string, reusedNames: readonly string[] | undefined,
        redirectedReference: ts.ResolvedProjectReference | undefined, options: ts.CompilerOptions,
        containingSourceFile?: ts.SourceFile): (ts.ResolvedModule | undefined)[] {
        // Custom implementation
        return moduleNames.map(function (moduleName: string): ts.ResolvedModule | undefined {
            if (moduleName.startsWith("node:")) return undefined; 
            const cacheMode = tsconfig.compilerOptions.module < 5 ? ts.ModuleKind.CommonJS : ts.ModuleKind.ESNext;
            const res = ts.resolveModuleName(moduleName, containingFile, options, host, cache, redirectedReference, cacheMode);
            if (res.resolvedModule === undefined) {
                for (const file of files) {
                    if (path.basename(file).substring(0, path.basename(file).length - path.extname(file).length) == moduleName) { 
                        const ret: ts.ResolvedModuleFull = { isExternalLibraryImport: file.split(path.sep).some(x => x == "node_modules"), resolvedFileName: file, extension: ts.Extension[path.extname(file)] };
                        cache.getOrCreateCacheForModuleName(moduleName, cacheMode, redirectedReference).set(objDir, { resolvedModule: ret });
                        return ret;
                    }
                }
            }
            return res.resolvedModule;
        });
    }

    const program = ts.createProgram(objFiles, tsconfig.compilerOptions, host, null, tsconfig.errors);
    const emitResult = program.emit();

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

Using Typescript to define property types based on their respective values

Is it possible to set a property type based on the property value? For example, if the command is: If 'set' then the payload must be PayloadSet If 'put' then the payload must be PayloadPut If 'del' then the payload must be ...

Assigning value to a member variable in a TypeScript Angular class

Currently, I am in the process of learning Angular. To enhance my skills, I am developing a simple web application using Angular and Spring Boot. One challenge I encountered is assigning a variable to the member variable of a Class. import { Injectable } f ...

Best practices for configuring a gulpfile.ts

I have configured a gulpfile.ts for my project based on this example from GitHub found here. (I won't be sharing my exact gulpfile.ts as it is similar, just slightly more complex) Every time I run a gulp task, I encounter these 4 errors: [11:53:23] ...

Utilizing the await keyword within a forkJoin operation in TypeScript

I am facing an issue where I need to fetch a new result based on the old result. When a specific parameter in my primary call is X, it should trigger another function. However, the problem I'm encountering is that the scope of the program continues ru ...

How to assign a new type to a class in Typescript

I am attempting to re-export a class with an internal type declaration in Typescript. My goal is for the re-exported class to be usable both as a class (with new) and as a type. Below is an example of what I have tried: class XReal { foo() {return 5} } dec ...

Encountering difficulty in removing a record from the database utilizing Prisma with Next.js API routes

Currently, I am in the process of developing a Todo manager using Next.js 13, Prisma, and MySQL. In order to include a feature that allows users to delete a todo item, I have implemented the use of a Link tag for the delete button within my code: ... <L ...

"Encountering issue with auto-import suggestions failing to appear in VS Code version 1.88.0

After installing the necessary libraries for MUI, I encountered an issue where basic components like Typography were not showing up in intellisense. Instead, it was displaying @mui/icons-material. You can view screenshots below: https://i.stack.imgur.com/ ...

The error message "Type 'Observable<void>' cannot be assigned to type 'void | Action | Observable<Action>' when integrating an effect" is displayed

Encountering an error when trying to add effects using the 'run' method. Attempted to manually return a string, number, and other types, but nothing seems to work. Here is the effects code snippet: @Effect() getRoles$: Observable<Roles[]> ...

Angular Compilation Blocked Due to Circular Dependency Error

Currently, I am utilizing WebStorm as my IDE to work on a personal project that I envision turning into a game in the future. The primary goal of this project is to create an Alpha version that I can showcase to potential employers, as I am actively seekin ...

Working with TypeScript: Overriding a Parent Constructor

I am new to TypeScript and currently learning about Classes. I have a question regarding extending parent classes: When we use the extends keyword to inherit from a parent class, we are required to call the super() method in the child class constructor. H ...

Implement code to execute exclusively on the initial success of react-query

I have a unique scenario where I need to utilize standard useQuery behavior, while also executing a piece of code only on the initial onSuccess event. Although I understand that I can accomplish this using useRef, I am curious if there is an alternative a ...

Unit testing in Angular 2+ involves testing a directive that has been provided with an injected window object

Currently, I am faced with the challenge of creating a test for a directive that requires a window object to be passed into its constructor. This is the code snippet for the directive: import { Directive, ElementRef, Input, OnChanges, OnDestroy, OnInit ...

The TypeScript error message indicates that a value typed as 'string | undefined' cannot be assigned to a type 'string'

In my TypeScript-based React application where I am utilizing material-ui for components, I am currently working on creating a wrapper for material-ui's input. Here is the code snippet: import FormControl, { FormControlProps } from "@material-ui/core ...

Using Bootstrap 4 with Angular 2: A Beginner's Guide

Currently, I am in the process of developing an Angular 2 application using TypeScript. My goal is to integrate the Bootstrap 4 framework with some custom theming. Is this achievable? I have encountered issues with the "ng2-bootstrap" npm package, as it d ...

How can I save a TypeScript object to Firebase using serialization?

Having an issue: Within my angular application, I have implemented a lot of classes with inheritance. However, upon attempting to save these objects to Firebase, I encountered an error indicating that I am trying to persist custom objects which is not supp ...

Removing background from a custom button component in the Ionic 2 navbar

Q) Can someone help me troubleshoot the custom component below to make it resemble a plus sign, inheriting styling from the <ion-buttons> directive? In my navbar, I've included a custom component: <notifications-bell></notifications-be ...

The component is failing to store its value within the database

I'm encountering an problem when attempting to save an option in the database. To address this issue, I created a component in Svelte called StatePicker that is responsible for saving US States. However, when I try to save it in the database using a ...

Issues with loading AddMarker on initial launch in Ionic 2

Can someone help me figure out what's causing the issue in my code? When I try to load a google map in my ionic 2 app, the marker doesn't show up the first time. It only appears when I reload the map for the second time or later. I also need ass ...

What is the correct approach for detecting object collisions in Phaser 3?

Hey everyone, I'm facing a problem and could use some assistance. Currently, I am trying to detect when two containers collide in my project. However, the issue is that the collision is being detected before the objects even start moving on screen. It ...

Exploring Appsetting Configuration in AppModule of Angular 8

I'm looking to update my configuration in the appsettings file by replacing a hardcoded string with a reference to the appsetting. Currently, I have this hardcoded value in appmodule.ts: AgmCoreModule.forRoot({ apiKey: 'testtesttest', li ...