Require()'ing a separated JS file without triggering typescript errors?


#1

Hi guys,

I got a Ionic layout from a coworker. I’m not 100% familiar with typescript and angular v2. I can work in her layout but I fail at just including an local JS file (i.e require("./functions.js"))

So the main goal is: include a local (read: in the src-folder) JS file in a .ts file (i.e a component) without setting of any linting alarms.

I tried a number of things, including:

  • Adding "allowJs": true, to tsconfig.json
  • Fiddling around with the .ts file where I require the file (I keep getting linting errors I can’t seem to ignore).

Doing a Google search returns out nothing. Please help, I took more time solving this than actually building the functions themselves :frowning:


#2

See: https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html

And: https://github.com/Microsoft/TypeScript/issues/5049


#3

Thanks, but unfortunately I couldn’t find a solution to my issue that easily. Let me explain:

Suppose I have this class:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-commonbike',
  templateUrl: 'commonbike.html'
})
export class CommonBikePage {

  constructor(public navCtrl: NavController) {

  }
}

What I want to do is to require() a set of functions I made ‘outside’ the ionic project and interact with them. I really don’t know how to get started. What I cam up with is something in the lines of this (which does not compile, maybe I’m not getting the right concept of typescript):

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { Functions } from './functions.js';

@IonicPage()
@Component({
  selector: 'page-commonbike',
  templateUrl: 'commonbike.html'
})
export class CommonBikePage {
  functions: object;

  constructor(public navCtrl: NavController) {
    var f = new Functions()
  }
}

So all in all, I don’t want to deal with typescript at all in regards to my contributions to our project (functions.js). It is fine that the ionic part is using it. So I’m trying to make a js-only interface that allows me to add anything without errors to the ionic-part.


#4

Just include the JS file in your index.html file.

To avoid TypeScript errors, just do something like this:

declare let CryptoJS: {
    enc: {
        Utf8: string
    }
    AES: {
        encrypt: (msg: string, pw: string) => string,
        decrypt: (encrypted: string, pw: string) => {toString: (x: any) => string}
    }
};

My Js file exposes a JS object called CryptoJS which has some properties and functions as shown above. Just declare this somewhere in TypeScript (If its just a function then something like declare let yourFunction: (params) => string or even just declare let yourFunction: any could just be enough).
Be aware that this declaration contains no implementation of the methods, just a hint for TS “hey here is an object called X with following properties/methods”.


#5

Thanks, unfortunately I can’t ‘include the JS file in your index.html file.’ (as in using script tags) becuase the file has imports itself. The only possible way would be to compile functions.js with webpack and then import the result using a script tag, I hope that’s won’t be necessary :stuck_out_tongue:

I also have these very weird errors when including the JS files:

[12:29:14]  typescript error 
            Cannot write file '/home/peter/Projects/app/src/app/functions.js' because it would overwrite 
            input file. 

[12:29:14]  typescript error 
            Cannot write file '/home/peter/Projects/app/src/utils/storagehelpers.js' because it would 
            overwrite input file.

When googling about this error often answers tell you to remove allowJS but that’s what I actually want.
My TSconfig is like this:

{
  "compilerOptions": {
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": [
      "dom",
      "es2015"
    ],
    "module": "es2015",
    "moduleResolution": "node",
    "sourceMap": true,,
    "target": "es5"
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ],
  "compileOnSave": false,
  "atom": {
    "rewriteTsconfig": false
  }
}

#6

Did you find a solution for this?

Running into exactly the same issue and coming across same suggestions like using script tag (which I can’t use for same reason as yours) and allowJs which then gave same problem: Cannot write file.


#7

moment.js example:


#8

Thanks, but it doesn’t fix this problem.

Using a js node-module in ionic ts works, but directly importing a js file which is not in node-modules doesn’t work.

I think it is because node-modules are compiled separately in the vendor.js (which seemingly supports js imports) and app’s src/ ts files are compiled separately using different typescript config etc… (which seemingly doesn’t allow js imports).

What is confusing is that typescript ‘allowJs’ is probably the official way to resolve this, but it doesn’t work due to other ionic build steps, either ‘Cannot write file’ error or if that is resolved using the outDir option then ‘Template not found’ error.


#9

-> Using a js node-module in ionic ts works, but directly importing a js file which is not in node-modules doesn’t work.

This worked for me:

I made a local copy of moment.js then imported it:

import moment from 'moment';

  ...

  public ngOnInit() {

    this.logger.info('IntroductionPage: ngOnInit()');

    let data = moment().format('YYYYMMDD');
    let time = moment().format('HHmmss');
    this.logger.info('today is: ', data + ' and time: ', time);
  }

Console:

45

See:


#10

Or you could package your *.js files as a node module:
https://docs.npmjs.com/getting-started/creating-node-modules

Or as a Cordova plugin (without any native code): https://cordova.apache.org/docs/en/latest/guide/hybrid/plugins/

Or: https://stackoverflow.com/questions/34140065/script-tag-in-angular2-template-hook-when-template-dom-is-loaded/44814222#44814222


#11

Thanks, creating a local node module to include js files worked like a charm. I am using it locally using ‘npm link’.