Tips for effectively identifying TypeScript SyntaxKind within TSLint

While creating custom TSLint rules, I encountered a reliability issue with (ASTObject).kind across different TypeScript versions.

For instance, in TypeScript version 3.4.5, the values for enum ts.SyntaxKind are ImportDeclaration = 249 and ImportClause = 250.

However, in TypeScript version 3.5.3, the same enums are changed to ImportDeclaration = 250 and ImportClause = 251.

This discrepancy caused issues with my lint rules. Is there a more effective method to identify this problem or a configuration error that might be causing the enum values to misalign?

I couldn't find any relevant documentation or discussions on this matter, which leaves me unsure if this is an oversight (unlikely) or if I am not utilizing it correctly.

export class Rule extends Rules.AbstractRule {
  public apply(sourceFile: ts.SourceFile): RuleFailure[] {

    for (const statement of sourceFile.statements) {

      // statement.kind / ts.SyntaxKind.ImportDeclaration
      // is 249 in TypeScript 3.4.5, 250 in TypeScript 3.5.3,
      // object property changes for target code, enum stays the same as lint source
      if (statement && statement.kind === ts.SyntaxKind.ImportDeclaration) {
        const importDeclaration: ts.ImportDeclaration = statement as ts.ImportDeclaration;

        // importDeclaration.moduleSpecifier.kind / ts.SyntaxKind.StringLiteral
        // 10 in TypeScript 3.4.5, 10 in TypeScript 3.5.3
        if (importDeclaration.moduleSpecifier && importDeclaration.moduleSpecifier.kind === ts.SyntaxKind.StringLiteral) {
          const moduleSpecifierStringLiteral: ts.StringLiteral = importDeclaration.moduleSpecifier as ts.StringLiteral;
        ...
        }

        // importDeclaration.importClause.kind / ts.SyntaxKind.ImportClause
        // is 250 in TypeScript 3.4.5, 251 in TypeScript 3.5.3
        // object property changes for target code, enum stays the same as lint source
        if (importDeclaration.importClause) {
          if (importDeclaration.importClause.namedBindings) {
            const namedBindings: ts.NamespaceImport | ts.NamedImports = importDeclaration.importClause.namedBindings;
            // namedBindings.kind / ts.SyntaxKind.NamedImports
            // is 252 in TypeScript 3.4.5, 253 in TypeScript 3.5.3
            // object property changes for target code, enum stays the same as lint source
            if (namedBindings && namedBindings.kind === ts.SyntaxKind.NamedImports) {
              const namedImports: ts.NamedImports = namedBindings as ts.NamedImports;
              for (const element of namedImports.elements) {
                const importName: string = element.name.text;
              ...
              }
            }
          }
        }
      ...
      }
    }
  }
}

Answer №1

One way to improve your code is by utilizing the "is-methods" in TypeScript, such as:

if (!ts.isImportDeclaration(statement)) {
    return;
}

I hope this tip proves useful for you ;)

Answer №2

The issue I faced was with my npm package where I used ts.isImportDeclaration(node) to retrieve import declarations, but it kept returning false despite the presence of import declarations in the file.

Upon investigation, I discovered that the problem stemmed from a version mismatch between the typescript dependency in my npm package and the one used in the application where my package was utilized. To resolve this, I adjusted the npm package configuration to specify typescript as a dev and peer dependency rather than a standard one.

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

Are there any secret "using" statements lurking within C# classes?

My app currently contains a Utils unit with only a few enums defined, including: public enum FavoriteStates { Colorado, Maine, Arizona } public enum UnfavorableStates { Ohio, Iowa, Kentucky } public enum StatesVisited { N ...

Implementing child components rendering in a React application using TypeScript

Just a little background information: I am attempting to build a carousel with pagination using ReactJS. Here is the code snippet I currently have: interface HTMLCarouselT { children: Array<JSX.Element> size: number; } const HTMLCarousel = ({ch ...

What are some effective ways to utilize the data gathered from a subscribe() method in a different

handleKeyUp(event: any): void { this.technologiesService.retrieveData(event.target.value) .subscribe(data => { this.myResults = data; }); } The result of data is: https://i.sstatic.net/WjiD4.png I want to assign data as a property fo ...

Integrate incoming websocket information with state management in React

I am facing a challenge in creating a timeseries plot with data obtained from a websocket connection. The issue arises when new values overwrite the previously stored value in the state variable. const [chartData, setChartData] = React.useState(null) Cu ...

I'm in the process of putting together a node.js project using typescript, but I'm a little unsure about the steps needed to

Currently, I am working on a node.js project that involves compiling with typescript. I recently realized that there is a directory named scripts dedicated to running various tasks outside of the server context, such as seed file operations. With files now ...

Converting JavaScript code containing ?? to TypeScript is not feasible

I've encountered a dilemma while attempting to convert several JS files with double question marks to TypeScript using tsc. Unfortunately, the tsc compiler does not recognize ??. For example: this.x = typeof params.x == "string" ? this._processStrin ...

Maintain the nullability of object fields when casting

I have been working on a type called DateToNumber that converts all the Date properties of an object to number. Here is what I have come up with so far: type LiteralDateToNumber<T> = T extends Date ? number : T extends Date | null ? number | nu ...

What's the process for deducing the default generic parameter from a function type?

Is there a way to extract the default type parameter of a function in order to make this statement compile successfully? const fails: string = "" as ReturnType<<T = string>() => T>; ...

Plot.ly, TypeScript, and the power of visualizing data with Scatter

I'm interested in creating a scatter plot within an Angular application using plot.ly. Most examples online utilize non-typed objects like this: var trace = { x: [1, 2, 3], y: [4, 5, 6], . . . } While I can follow this method, I prefer ...

Guide to utilizing vue-twemoji-picker in TypeScript programming?

Has anyone encountered this issue when trying to use vue-twemoji-picker in a Vue + TypeScript project? I keep receiving the following error message. How can I fix this? 7:31 Could not find a declaration file for module '@kevinfaguiar/vue-twemoji-picke ...

Navigating through Angular iterator loops

In one of my components, I have the following method: public *numGen(): Iterator<number> { for (let i = 0; i < 5; ++i) yield i; } Additionally, my HTML contains this snippet: <p *ngFor="let n of numGen()">{{n}}</p&g ...

Angular 12 - Issue: None of the available overloads match this call. Overload 1 out of 5

Here is the code snippet I am working with: import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { BehaviorSubject } from 'rxjs'; import { HttpClient } from '@angular/common/http&ap ...

The property 'key' is not found within the type 'string | { key: string; element: Element; }'

Why is this error message appearing? The issue states: Property 'key' does not exist on type 'string | { key: string; element: Element; }' It seems to be triggered by the following code: <th key={header?.key ? header.key : header} r ...

What is the process for creating a method within a class?

Here is the current structure of my class: export class Patient { constructor(public id: number, public name: string, public location: string, public bedId: number, public severity: string, public trajectory: number, public vitalSigns: ...

In Angular 7, where can the controller be found within its MVC architecture implementation?

From what I understand, Angular adheres to the MVC architecture. In the components, there is a .ts file which serves as the model and a .html file for the view, but my question is: where is the controller located? ...

Strict mode enhances the security and reliability of map data structures

Utilizing strict mode in my code has led to an issue when trying to assign an object value from a Map. Despite the fact that the value obtained from the Map is not undefined, strict mode is throwing the error Type A[]|undefined isn't assignable to typ ...

A TypeScript function that converts a value into an array if it is not already an array, ensuring the correct type is output

I'm attempting to develop a function that wraps a value in an array if it is not already an array. export function asArray<T extends Array<any>>(value: T): T export function asArray<T>(value: T): T[] export function asArray(value: a ...

What could be causing the on:click event not to function in Svelte?

I need some assistance with displaying a text input field based on the value of the "changeEmail" variable. I have a handleClick function that toggles the value of "changeEmail" between true and false, but when I click on a button, nothing happens. Any gui ...

Create a conditional statement based on the properties of an object

In one of my Typescript projects, I am faced with the task of constructing a dynamic 'if' statement based on the data received from an object. The number of conditions in this 'if' statement should match the number of properties present ...

Discover the most helpful keyboard shortcuts for Next.js 13!

If you're working with a standard Next.js 13 app that doesn't have the experimental app directory, setting up keyboard shortcuts can be done like this: import { useCallback, useEffect } from 'react'; export default function App() { c ...