I have to consume some ES6 JavaScript code (so, just a bunch of ES6 files, not a 3rd party library) from a Typescript file, in the context of an Angular app (or library). Given that's a corner usage case, I cannot find much information by googling around (most directions refer to importing JS libraries), except for what I have already done; yet, I'm still having issues.
As a test, I just created a new Angular 13 workspace (ng new test
), without routing and with plain CSS. Then, I made these changes to its default template:
(1) in tsconfig.json
, I added "allowJs": true
(reference here) to the compiler options. The result is:
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2017",
"module": "es2020",
"lib": [
"es2020",
"dom"
],
"allowJs": true
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}
(2) added a dummy JS module under /src/assets/js/hello.js
with this content:
// just to be explicit, yet strict is implied by export:
// see https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export
'use strict';
export const SOME_CONSTANT = 10;
export function sayHello(name) {
console.log('Hello ' + name);
}
(3) included the JS file in the app via angular.json
(under architect/build/options/scripts
):
"scripts": [
"src/assets/js/hello.js"
]
(4) imported sayHello
into app.component.ts
:
import { Component } from '@angular/core';
import { sayHello } from 'src/assets/js/hello';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor() {
sayHello('world!');
}
}
(5) added src/typings.d.ts
to include ambient type declarations, with this content:
declare function sayHello(name: string): void;
Now, the app builds, and the function gets invoked and outputs its message on the console; but there are a couple of issues:
at runtime I get error
Uncaught SyntaxError: Unexpected token 'export'
. This would appear to point at a JS script loaded withouttype="module"
(see e.g. this post), but scripts are loaded viaangular.json
here, so they should already be loaded as modules (as it appears from here). The default value formodule
intsconfig
ises2020
, so this post does not seem to apply.typings do not seem to be in effect. I can e.g. remove the string argument from
sayHello
andng build
succeeds, despite the argument being declared intypes.d.ts
(and of course I get no typed intellisense in VSCode forsayHello
).