How to import a library in non-strict mode in strict Angular app?

Viewed 537

I'm trying to import jschardet in an Angular 11 project. The current version 3.0.0 does not run in strict mode (throws TypeError at runtime). I tried to reproduce this issue in a minimal example. Therefore, I generated a new Angular project and used the same dependencies and configuration (i.e. I use the same tsconfig.json, tsconfig.app.json, angular.json, package.json and package-lock.json in both projects). However, the TypeError only occurs in my large/original project. I failed to reproduce it in a smaller project. I guess that my large project runs jschardet in strict mode somehow (even though I didn't specified it explicitly in the mentioned files), but my new project doesn't runs jschardet in strict mode. I don't know, which files would be relevant to share to figure this out. Please let me know in the comments.

Anyhow, I wouldn't like to run my Angular app in non-strict mode, just one imported library requires non-strict mode. How can I import/call a specific library in non-strict mode?


Files, versions and further information below:

  • jscharder 3.0.0
  • TypeScript 4.0.5
  • @angular/compiler 11.1.0

src/app/app.component.ts

import { Component } from '@angular/core';
import * as jschardet from 'jschardet';

@Component({
  selector: 'app-root',
  template: `
      <input type="file" id="file" (change)="decode($event)">
  `
})
export class AppComponent {
  decode(e: any) {
    const file = e.target.files[0];
    console.log(typeof file);
    const fileReader = new FileReader();
    fileReader.onload = function() {
      const array = new Uint8Array(fileReader.result as ArrayBuffer);
      let string = "";
      for (let i = 0; i < array.length; ++i) {
        string += String.fromCharCode(array[i]);
      }
      console.log(jschardet.detect(string));
    };
    fileReader.readAsArrayBuffer(file);
  }
}

tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "importHelpers": true,
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "downlevelIteration": true,
    "target": "es2015",
    "typeRoots": [
    ],
    "lib": [
      "es2017",
      "dom",
      "dom.iterable"
    ],
    "types": [
      "node",
      "core-js"
    ],
    "module": "es2020",
    "baseUrl": "./"
  }
}

src/tsconfig.json

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "outDir": "../out-tsc/app",
    "baseUrl": "./",
    "types": [ "node" ],
    "typeRoots": [ "../node_modules/@types" ]
  },
  "angularCompilerOptions": {
    "fullTemplateTypeCheck": true,
    "strictInjectionParameters": true
  },
  "files": [
    "main.ts",
    "polyfills.ts"
  ],
  "include": [
    "src/**/*.d.ts"
  ]
}

angular.json (shortened)

{
  "projects": {
    "my-app": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "aot": true,
            "outputPath": "dist",
            "index": "src/index.html",
            "main": "src/main.ts",
            "tsConfig": "src/tsconfig.app.json",
            "polyfills": "src/polyfills.ts"
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "my-app:build"
          }
        }
      }
    }
  }
}

I run both projects using ng serve.

1 Answers

I discovered a workaround. It is working if I use a dynamic import

const jschardet = await import('jschardet');
console.log(jschardet.detect(string));

I still don't know exactly why. If I use a regular import, the library is part of the built bundle vendor.js, which defines

"use strict";

If I use a dynamic import, the library is a separate module file that does not define

"use strict";

I'm not sure, if this workaround works in general. Please add another answer or comment if you know more.

Related