Having trouble incorporating @types/pdfmake into an Angular project

I have been experimenting with integrating a JS library called pdfmake into an Angular application. I found some guidance on how to accomplish this at https://www.freecodecamp.org/news/how-to-use-javascript-libraries-in-angular-2-apps/, which involved using the @types/pdfmake package.

To install @types/pdfmake, I used the following command:

npm install --save @types/pdfmake
  

In one of my components, I imported pdfmake like this:

import * as pdfMake from 'pdfmake/build/pdfmake';  
import * as pdfFonts from 'pdfmake/build/vfs_fonts';
(<any>pdfMake).vfs = pdfFonts.pdfMake.vfs;
  

To leverage the types in pdfmake, I included the following import:

import * as _ from 'pdfmake';
  

However, upon doing so, I encountered this error:

This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.
  

In attempting to address this issue, I made adjustments to my tsconfig.json file as shown here:

{
  "compileOnSave": false,
  "allowSyntheticDefaultImports":true,
  "esModuleInterop": true,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2015",
    "module": "es2020",
    "lib": [
      "es2018",
      "dom"
    ]
  }
}
  

Despite these modifications, the error message regarding ECMAScript imports/exports persisted.

Edit:

I revised the tsconfig file to the following configuration:

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "allowSyntheticDefaultImports":true,
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2015",
    "module": "es2020",
    "lib": [
      "es2018",
      "dom"
    ]
  }
}
  

However, the error persisted even after this adjustment.

Answer №1

To ensure it works properly, include your allowSyntheticDefaultImports setting within the compilerOptions block instead of outside it.

`"compilerOptions": { "allowSyntheticDefaultImports":true, }

Answer №2

function importAndNormalize<T>(
  resourcePromise: Promise<T>
): Promise<T> {
  // Normalizing CommonJS imports to ESModule format by handling 'default' property
  return resourcePromise.then((resource: any) => (resource.default || resource) as T);
}

// Dynamically loading pdfmake library using import()
const importPdfMake = importAndNormalize(import('pdfmake/build/pdfmake.min'));

const importPdfFonts = importAndNormalize(import('pdfmake/build/vfs_fonts'));


// Implementation in a service or component
async function generatePDFDocument(): Promise<void> {
    const pdfMake = await importPdfMake;
    const pdfFonts = await importPdfFonts;

    pdfMake.vfs = pdfFonts.pdfMake.vfs;
    const docDefinition: TDocumentDefinitions = {
       content: [
         'First paragraph',
         'Another paragraph, this time a little bit longer to ensure it wraps into multiple lines',
       ],
    };
    pdfMake.createPdf(docDefinition).open();
  }

In addition, the tsconfig should have the setting

"module": "ESNext"
or higher for dynamic loading of libraries.

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

Building a different theme using the ng or npm command can be achieved by following these steps

In an attempt to utilize different npm commands for building distinct themes, such as running 'npm run red' (to launch index with red.html) or 'npm run blue' (to initiate index with blue.html). npm run red npm run blue I have configur ...

Cypress automation script fails to trigger Knockout computed subscription

Within my setup, I have implemented two textboxes and a span to display the result. Date: <input data-bind="value: dateValue"/> Number: <input data-bind="value: dateValue"/> Result : <span data-bind="text: calculatedValue">Result Should ...

Utilizing TypeScript to define the parameter of a method within a generic interface by extracting a value from the generic type

In search of defining a versatile interface that can manage any Data type, I came up with an idea. This interface includes a dataKey property which simply holds a value of keyof Data. Additionally, it features a handler function where the parameter type sh ...

Resolving the Angular NG0100 Error: Troubleshooting the ExpressionChangedAfterItHasBeenCheckedError

I am currently working on implementing a dialog component that takes in data through its constructor and then utilizes a role-based system to determine which parts of the component should be displayed. The component code snippet looks like this: export cl ...

Compilation with Webpack and Postcss failed due to the inability to locate the scss file within the library in node_modules

Here is the layout of my project structure: node_modules dist config - webpack.common.js - webpack.dev.js - webpack.prod.js - webpack.test.js src - app - app-routing.module.ts - app.component.html - app.component.scss - app.compo ...

Creating a TypeScript interface for Immutable.js objects: A step-by-step guide

Imagine we are working with the following interface User: interface User { id: number; name: string; bag: Item[]; } Now, let's create a React component: interface UserComponentProps { user: User; } interface UserComponentState {} class Use ...

The issue with launching a Node.js server in a production environment

I'm currently facing an issue when trying to start my TypeScript app after transpiling it to JavaScript. Here is my tsconfig: { "compilerOptions": { "module": "NodeNext", "moduleResolution": "NodeNext", "baseUrl": "src", "target": " ...

What is the reason for not being able to call abstract protected methods from child classes?

Here is a simplified version of my project requirements: abstract class Parent { protected abstract method(): any; } class Child extends Parent { protected method(): any {} protected other() { let a: Parent = new Child() a.me ...

Transforming a "singular or multiple" array into an array of arrays using TypeScript

What is causing the compilation error in the following code snippet, and how can it be resolved: function f(x: string[] | string[][]): string[][] { return Array.isArray(x[0]) ? x : [x]; } Upon inspection, it appears that the return value will constantly ...

Is it possible to access your app directly from the browser without requiring any user prompts?

After successfully setting up my app for both android and ios with the necessary app link and universal link, I am now focusing on redirecting users from a specific website to my app. The mobile aspect is all set, but I need to work on the browser/server s ...

How can I gather information from members who have already signed up?

I have a form that submits data to the Angular Firebase database. Once the form is submitted, I want to display the previously submitted data in the form if the user signs in again. Below is my .ts file: import { Component, OnInit } from '@angular/c ...

In response to resolving an HTTP header issue with a status of 200 ok during API testing with Postman, what steps can be taken

Hello everyone, I am new to the world of Angular and facing some issues while learning. Following a tutorial on YouTube, I tried to replicate the process with a few modifications. Initially, my get API worked fine when tested with Postman, and the post API ...

Experiencing 429 Too Many Requests error on Angular 7 while attempting to perform multiple file uploads

Whenever I attempt to upload a large number of files simultaneously, I encounter an issue. The API interface only allows for the submission of one file at a time, requiring me to call the service for each individual file. Currently, my code looks like thi ...

typescript - add a global library import statement to every script

Recently, I began working on a TypeScript project in Node.js. I am looking to add import 'source-map-support/register'; to all of my .ts files for better visibility of TS source in stack traces. Is there a method to implement this without manuall ...

Jest is having difficulty locating a module while working with Next.js, resulting in

I am encountering some difficulties trying to make jest work in my nextjs application. Whenever I use the script "jest", the execution fails and I get the following result: FAIL __tests__/index.test.tsx ● Test suite failed to run ...

Error [ERR_MODULE_NOT_FOUND]: Unable to locate the specified module (TypeScript/TypeOrm)

I'm encountering an issue where the content of my database is not being printed when using an entity with TypeScript/TypeOrm. Here's the code I have: Main file : import { createConnection, getManager ,getConnectionOptions } from 'typeorm&a ...

Unable to access structuredClone on the global object within a Node.js application

structuredClone is causing issues in my NodeJS application. Whenever I try to utilize it, I encounter the error: structuredClone is not defined nodejs. To troubleshoot, I created a simple file and executed the following: console.log({ globals: Object. ...

Issue with Angular 6 Material2 mat-table MatRipple causing errors

When I try to use MatTable with a data source in Angular 6 and add sorting or pagination, I encounter the following error: ERROR Error: Uncaught (in promise): Error: Can't resolve all parameters for MatRipple: ([object Object], [object Object], [ob ...

Step-by-step guide on utilizing the vendor.ts file available at https://angular.io/docs/ts/latest/guide/webpack.html

As per the guidelines provided at https://angular.io/docs/ts/latest/guide/webpack.html, it is recommended to include vendors like jQuery in the vendor.ts file. // Other vendors for instance jQuery, Lodash or Bootstrap // You can import js, ts, css, sass, ...

Hide the navigation menu when a page link is selected

Within my Angular 8 application, a fixed navigation bar is positioned at the top of the screen. Upon hovering over a dropdown nav link, a menu will appear for the user to explore. However, when a user clicks on one of these menu links, Angular Routing is ...