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

Expanding a class in Typescript by adding a function with the same name but varying properties and types

class A { play(a: string): string{ return a; } } class B extends A { play(c: string, b: number): string{ return c + ' ' + b.toString(); } } let x = new A(); console.log(x.play('John')); let y = new B(); console.lo ...

Angular 2 module transpilation services

In my angular 2 application, there is a module called common. Here is how the project structure looks like: main --app /common --config //.ts configs for modules --services //angular services --models --store //ngrx store /co ...

What is the best way to refine the dataSource for a table (mat-table) using ngx-daterangepicker-material?

I am facing a new challenge and feeling unsure about how to approach it. The issue at hand is filtering a table based on the date range obtained through the ngx-daterangepicker-material library. This library triggers events that provide a start date and a ...

Updating documents within an array in MongoDB is a common task that can be easily accomplished

Trying to modify a specific property within my MongoDB document. This is how the document is structured: "_id" : ObjectId("57e2645e11c979157400046e"), "id" : 1651570992420, "creator" : "nameHere ...

Can the Angular CLI be installed without using the command prompt?

Are there alternative methods for installing angular cli besides using the command line in cmd? I am encountering proxy setting issues when trying to install it using npm install -g @angular/cli (I am currently using a VPN for work) npm ERR! code ETIMEDOUT ...

Show objects based on issuance date

I have implemented a function to retrieve a list of items from a feed URL as shown below: getFeed(){ return Observable.interval(5000) .mergeMap(() => this._http.get(this.feedUrl)) .map(this.extractFeeds) .catch(this.handleError ...

Error in TypeScript: Circular reference in type alias 'Argument' in node_modules/classnames/index.d.ts at line 13:13

Need help troubleshooting an error while building my project. Can't find much information online to resolve this issue. I am using typescript 4.2.4 I can't locate the classnames/index.d.ts file in any directory, so I'm unable to make any ch ...

Error in VueJS/Typescript: Module 'my-module' or its type declarations are not found

Hey fellow developers! I'm currently working on a Vue2 setup with Nuxt and Typescript. I'm facing an issue while trying to install the awesome vue-slick-carousel module via yarn. When attempting to import the module in my component, Typescript th ...

Creating a dynamic table in HTML and Angular is a simple process that involves utilizing the

How can I create an HTML table dynamically without knowing the template of each row in advance? Sometimes it may have 2 columns, sometimes 4... I am looking for something like this: <div> <h1>Angular HTML Table Example</h1> < ...

Access your Angular 2 application on an external device during the development process

Is there a way to view your app in an external device like a cell phone web browser, instead of just running npm start and viewing it in your desktop browser? ...

The module rxjs/operators cannot be located

When trying to import rxjs/operators in my Angular project, I use the following syntax: import { map } from 'rxjs/operators'; However, this results in the following error message: map is declared but its value is never read. Cannot find modu ...

Guide to resolving the issue of error Type 'void[] | undefined' cannot be assigned to type 'ReactNode'

I am attempting to map the data Array but I am encountering an error: Type 'void[] | undefined' is not assignable to type 'ReactNode'. Can someone please assist me in identifying what I am doing wrong here? Below is the code snippet: i ...

Problem integrating 'fs' with Angular and Electron

Currently, I am working with Angular 6.0, Electron 2.0, TypeScript 2.9, and Node.js 9.11 to develop a desktop application using the Electron framework. My main challenge lies in accessing the Node.js native API from my TypeScript code. Despite setting "com ...

Converting Angular 5 select option values to strings is a must

I have set up a basic select connected to a variable like this: <select id="client" name="client" [(ngModel)]="order.clientId"> <option *ngFor="let client of clients" [value]="client.id"> {{ client.name }} </option> </ ...

Angular is having trouble with the toggle menu button in the Bootstrap template

I recently integrated this template into my Angular project, which you can view at [. I copied the entire template code into my home.component.html file; everything seems to be working fine as the CSS is loading correctly and the layout matches the origina ...

What is the method for defining a mandatory incoming property in an Angular2 component?

In my current project, I am developing a shared grid component using Angular2 that requires an id property. export class GridComponent { @Input() public id: string; } I'm looking for a way to make the id property mandatory. Can you help me with ...

Avoiding the use of destructuring for undefined values in JavaScript can be achieved by implementing

Upon receiving the response registryReportSettings from the server: this.getRegistrySettings(registry.Id).subscribe((registryReportSettings: { extended: ReportPropertiesRequest }) => { const { objectProperties, reportProperties, textProperties } = reg ...

Issues with connecting to server through Angular websocket communication

I deployed the server on an Amazon AWS virtual machine with a public IP address of 3.14.250.84. I attempted to access it using Angular frontend like so: public establishWebSocketConnection(port : number){ this.webSocket = new WebSocket('ws://3.14.250. ...

Issue encountered while generating menu using Angular's Material framework

In my Angular project, I am working on creating a right-side menu with specific functionalities. While the Home and Photo menus work perfectly, I am encountering an issue with the Admin menu. I intend to have 2 submenus open when clicking on the Admin tab, ...

Is it more beneficial to convert all the current jQuery AJAX webparts into Typescript or should I opt to inject the existing jQuery into SPFX instead?

Transitioning from SharePoint 2013 to SharePoint online raises the question of how to migrate existing webparts that utilize jquery - ajax to SPFX client webparts. One possibility is rewriting all the code in Typescript, but is it possible to simply inje ...