Creating TypeScript type definitions for a CommonJS module

I've been grappling with getting xmllint to function correctly within Typescript.

Given that it's written in traditional JS, attempting to import the module directly into Typescript results in a compile error:

Cannot find module 'xmllint' or its corresponding type declarations.

To resolve this issue, I created an index.d.ts file in my root directory :

declare module 'xmllint'{
    export interface ValidationResult{
        errors: string[]
    };
    export interface Options{
        xml: string, xsd:string
    }
    export function validateXML(opts: Options): ValidationResult;
}

Although this now compiles without errors, I'm unable to successfully import the module into a Typescript class. It consistently either returns an empty object or undefined.

I have attempted:

  • import {validateXML} from "xmllint"
    , resulting in an empty object for validateXML
  • import validateXML from "xmllint"
    , causing validateXML to be undefined
  • import * as validate from "xmllint"
    , leading to validateXML being an empty object

Shown below is my tsconfig.json

{
  "compilerOptions": {
    "target": "es2016",
    "module": "esnext",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve"
  },
  "include": [
    "src"
  ]
}

It seems like the issue lies in my index.d.ts not properly referring to the native xmllint function, but I'm unsure of how to address this.

What am I overlooking?

Answer №1

The xmllint module is a default export in CommonJS, meaning it is exported as module.exports = xmllint, where xmllint is an object with the property validateXML as a function. To define its type in TypeScript, you can do something like this -

declare module "xmllint" {
  export interface ValidationResult {
    errors: string[];
  }

  type Options = { xml: Array<string>; xsd: Array<string> };

  type XMLLint = {
    validateXML(options: Options): ValidationResult;
  };

  const xmllint: XMLLint;

  export default xmllint;
}

After adding this definition, ensure that Typescript recognizes it by including an entry in your tsconfig.json. Then, you can use it by importing it as shown below -

import fs from "node:fs";
import xmllint from "xmllint";

const xml = fs.readFileSync("./src/test.xml").toString();
const schema = fs.readFileSync("./src/test.xsd").toString();

console.log(xmllint.validateXML({ xml: [xml, xml], xsd: [schema, schema] }));

The output for the test files using the package itself was:

{
  errors: [
    "file_0.xsd:1: parser error : Start tag expected, '<' not found",
    'undefined',
    '^',
    "Schemas parser error : Failed to parse the XML resource 'file_0.xsd'."
  ]
}

You can access the Codesandbox link here.

P.S - Take note that any type errors in Codesandbox are due to the environment, and you should not encounter them in IDEs like VS Code.

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

Looking to generate a temporary query in VSTS? The createquery() function is perfect for this task, but be cautious as using getquery()

let searchQuery = "Retrieve [System.Id], [System.Title], [System.State] For WorkItems Where [System.WorkItemType] = 'Bug' sort by [Microsoft.VSTS.Common.Priority] in ascending order, then by [System.CreatedDate] ...

Chart.js:9352 Error in generating chart. Dynamic chart creation unsuccessful

I encountered an issue while attempting to dynamically generate charts in my Angular project. Error: Chart.js failed to create chart due to inability to acquire context from the given item. export class StudentStudyProgressComponent implements OnInit ...

Navigating through alterations in intricate data utilizing the BehaviorSubject concept

If I have a Service that offers a BehaviorSubject to any component needing the most up-to-date version of certain data, how can these components differentiate what changed in the data when they receive notifications? export class DataService { pri ...

Is it possible for a TypeScript interface to inherit from a Function?

While studying Angular, I found this intriguing declaration: interface IMessagesOperation extends Function { (messages: Message[]): Message[]; } I'm curious about what this means, especially why Function is capitalized as F instead of being lowercase ...

What is the best way to pass on the isPending status (from useTransition) to parent components?

In my codebase, I have a standard component known as ClientButton. This component essentially wraps a Server Action using startTransition to create an event handler: 'use client'; export default function ClientButton({ onClick, buttonText, class ...

Incorporating a Script into Your NextJS Project using Typescript

I've been trying to insert a script from GameChanger () and they provided me with this code: <!-- Place this div wherever you want the widget to be displayed --> <div id="gc-scoreboard-widget-umpl"></div> <!-- Insert th ...

Issue with Bot framework (v4) where prompting choice in carousel using HeroCards does not progress to the next step

Implementing HeroCards along with a prompt choice in a carousel is my current challenge. The user should be able to select options displayed as HeroCards, and upon clicking the button on a card, it should move to the next waterfall function. In the bot fr ...

What is the best way to adjust the Material Drawer width in Reactjs to match the width of its children?

Currently, I am utilizing the Material-ui Drawer component to toggle the display of content on the right side of the screen. The functionality I am aiming for is that when the Drawer opens, it will shrink the existing content on the right without any overl ...

What is the best way to programmatically define the value for the MaterialUI grid size property using TypeScript?

Is there a way to dynamically pass a value to the Grid size props like XL in TypeScript? For instance, *Update for further clarification import Grid, { GridSize } from "@material-ui/core/Grid"; let value: GridSize = 12/4; xl={value} Error: Type &apos ...

Exploring the world of TypeScript and JSON.stringify functions in JavaScript

In this simplified scenario: export class LoginComponent{ grant_type: string="password"; jsonPayload: string; Login(username, password){ this.jsonPayload = JSON.stringify({ username: username, password: password, grant_type: this.g ...

Lazy loading in Angular - struggling to verify its functionality

A module for lazy loading was created by me. This particular module is called SettingsRoutingModule- const routes: Routes = [ { path: '', component: SettingsStandaloneComponent, children: [ ...

Error encountered: Mongoosastic search doesn't work properly in TypeScript environment

Currently, my setup involves using mongoose v6.0.0, mongoosastic v5.0.0, and integrating typescript. However, even after initializing the plugin and attempting to correctly set the types, I am encountering issues where functions like PageModel.search intro ...

How to access the types of parameters in a function type

I am working on a function that takes a value and default value as arguments. If the value is a boolean, I want the return type to match the type of the default value. Here is the function I have: export type DetermineStyledValue<T> = ( value: str ...

Consistentize Column Titles in Uploaded Excel Spreadsheet

I have a friend who takes customer orders, and these customers are required to submit an excel sheet with specific fields such as item, description, brand, quantity, etc. However, the challenge arises when these sheets do not consistently use the same colu ...

Tips for customizing the font color in Material UI Typography

Is it possible to change the color of only this text to red? return <Typography style={{ color: 'red' }}>Login Invalid</Typography> I came across this online solution, but I am unsure how to implement it as there is no theme={color ...

The integration of react-color Saturation with @types/react-color is currently unavailable

In my quest to develop a customized color picker, I am utilizing the react-color library (^2.19.3) together with @types/react-color (^3.0.4). The issue arises when trying to import the Saturation component since it is not exported from the types in the ind ...

typescript function intersection types

Encountering challenges with TypeScript, I came across the following simple example: type g = 1 & 2 // never type h = ((x: 1) => 0) & ((x: 2) => 0) // why h not never type i = ((x: 1 & 2) => 0)// why x not never The puzzling part is w ...

Using TypeScript to categorize items based on common characteristics and assigning them a unique group ID

I am looking to create a function that can achieve the following: Accepts an array of products as input Returns a new array of products with a unique groupId attribute for each Products will share the same groupId if they have common attributes specified ...

Function returning promise asynchronously, but caller function failing to resolve the promise

I have been researching similar items without success and I realize that I need a better understanding of promises, but I am facing some challenges. My project involves Ionic 4/Angular 8 with an Azure-based backend. I am trying to display images from Azur ...

Issue with the scoring algorithm using Angular and Spring Boot

Hello, I have created a scoring algorithm to calculate scores, but I encountered an error in "salaireNet". ERROR TypeError: Cannot read properties of null (reading 'salaireNet') at ScoringComponent.calculateScore (scoring.component.ts:33:55) ...