Typescript module loading error - javascript

I have a file module.d.ts with declaration
declare module "ArrayItem" {import out = require("models/ArrayItem"); export = out;}
Now I have a file Array.ts and the first line is
/// <reference path="../module.d.ts" />
import array = require("ArrayItem").
But this is not working. I got script error.
If I use,
/// <reference path="../module.d.ts" />
import array = require("models/ArrayItem")
Then I did not get any error.
What is the issue in module loading here?
If I have a module.d.ts, then the arrayitem module should be loaded from require("arrayitem").
Correct? Or should I always the correct path for ArrayItem?
I am confused here. Can someone throw help here?

If you are the owner of ArrayItem.ts then you don't need module.d.ts. Just reference the module directly.
You are getting a runtime error but not a compiler error because your runtime is trying to load ArrayItem.js for the current path and not from models/ArrayItem. There is no point in your module.d.ts file since it is only a wrapping of the definitions (but not code) in the typescript module, which your already going to pick up with a direct reference to the module.
So, don't use the /// and import using require("models/ArrayItem").

Related

Referencing vanilla js file in TypeScript getting file is not a module

I'm trying to import a file into TypeScript that's basically just a js file that you'd put into a tag. I've tried a few different things.
// global.d.ts
declare module 'myfile.js'
Inside of the react file:
// component.tsx
import { foo } from '../lib/myFile.js' // This is saying it is not a module
Inside of the js file, it looks like this a few times so not sure how I need to reference the file:
(function( something ) {
something.Foo = function (){}
}(window.something = window.something || {}));
Any thoughts on how I could use this file? Do I need to go through and declare typings for everything in it?
EDIT: I've added allowJS to my tsconfig but it still doesn't work.
You can only import what is exported from the file.
If your file contains only immediately invoked functions, or top level code, you only need to import the file itself like this:
import '../lib/myFile.js'
This is a little weird, however. I would suggest wrapping everything with a function and exporting then importing that function instead.

Cypress not recognizing my imported module from outside /cypress directory

I am trying to import a module from a file outside my /cypress directory into the /cypress/integration directory's test.spec.js file like so:
import { LAB_MODEL } from '../../models/search/lab-model';
But inside this imported module "LAB_MODEL" there are other files being imported using the "##" at the start of the file imports like
import ExperimentDetails from "##/components/experiment/ExperimentDetails";
and I think this is why Cypress isn't working and giving me this error:
Error: Webpack Compilation Error
./models/search/lab-model.js
Module not found: Error: Can't resolve '##/components/experiment/ExperimentDetails' in '/Users/hidden/models/search'
resolve '##/components/experiment/ExperimentDetails' in '/Users/hidden/models/search'
Parsed request is a module
using description file: /Users/hidden/package.json (relative path: ./models/search)
Field 'browser' doesn't contain a valid alias configuration
resolve as module
So I think this is the reason why my test won't run, but I have no idea how to make Cypress recognize "##" imports and can't find any documentation/stackoverflow answers, any help is appreciated, thanks!
##/ looks like something that gets translated into a full path during the Nuxt build.
(ref The alias Property).
Cypress has a separate build that doesn't know about this Nuxt feature. You could try to replicate it with some webpack config via a preprocessor, but another way is to have your Nuxt app put a reference to lab_model on the window object
// somewhere in the Nuxt app
if (window.Cypress) {
window.lab_model = LAB_MODEL;
}
then at the top of the test
const lab_model = cy.state('window').lab_model;
This has the benefit of giving you the exact same instance of lab_model, in case you wanted to stub something.
In a starter Nuxt app, I added the code window.lab_model = LAB_MODEL in /pages/index.vue, but you can add it in any component that imports it, right after the import statement.
In the spec add a .should() to test the property exists, to allow the app time to settle.
it('gets labModel from the Nuxt app', () => {
cy.visit('http://localhost:3000/')
cy.window()
.should('have.property', 'lab_model') // retries until property appears
.then(labModel => {
console.log(labModel)
// test with labModel here
})
})

How do I call a function in an external js file using typescrpt

We are trying a POC of adding Typescript and Webpack to our Angularjs project.
I am able to get my webpack bundle to generate, however at runtime the program cannot find the various functions in my validator.js. Can you please offer some advice?
login-view.components.ts
declare var findFormNode: any; //function in validator.js
//LogInUser
self.login = function ($event, command) {
if (findFormNode($event.target.id)) {
...
}
}
main.ts is importing the file
import "./../../../CommonStaticFiles/include/js/Validators.js";
bundle.js
eval("/* WEBPACK VAR INJECTION */(function($) {/*\r\n\r\n VALIDATORS\r\n\r\n ... n\n\nfunction findFormNode(
error
ReferenceError: findFormNode is not defined
at LoginController.self.login (login-view.component.ts:28)
at fn (eval at compile (angular.js:NaN), <anonymous>:4:267)
at callback (angular.js:29019)
In order for your functions to be properly imported, there are few things that you have to make sure of.
First, make sure you are exporting your functions correctly. Here's an example of how to export a function from Validator.js:
export const validateFunc1 = ():void => {};
Next, you have to make sure you are using proper import syntax. In order to import the function above, you would do the following:
import {validateFunc1} from "./../../../CommonStaticFiles/include/js/Validators.js";
Alternatively, if you want to import all exported functions at once, then you can use this syntax:
import * as validatorFuncs from "./../../../CommonStaticFiles/include/js/Validators.js";
Lastly, check that the location of Validators.js is correct. It's a common mistake to be looking in the wrong directory. Your code editor can usually help you find the right path to use.

inject a require into a js vendor module

About the framework (while I think the problem itself does not heavily rely on that): Angular 2 with Webpack
There is the library Leaflet.heat which relies on simpleheat. I got the missing type definitions under control.
I'm importing the libraries in my vendor.ts
[...]
import 'simpleheat';
import 'leaflet.heat/src/HeatLayer';
[...]
Inside of the HeatLayer class, the function simpleheat:
[simpleheat.js]
if (typeof module !== 'undefined') module.exports = simpleheat;
function simpleheat(canvas) {
...
is called. However, the HeatLayer module file does not require simpleheat inside it's file.
Thus, creating an instance of L.HeatLayer works, but the execution of the respective code in it's function fails with
ReferenceError: simpleheat is not defined
Now, adding (for testing purposes) simpleheat = require('simpleheat'); into the HeatLayer file (a vendor), it works.
Understandably, I don't want to modify a vendor file.
Question:
What options do I have, to make the function simpleheat accessible from inside the HeatLayer module?
One Solution I just found:
Change the vendor.ts to the following:
(<any>window).simpleheat = require('simpleheat');
import 'leaflet.heat/src/HeatLayer';
Are there others/better?

Avoid duplicate reference / import of external javascript library in Typescript when using AMD modules

Lets say I am using --module AMD to get AMD module support with Typescript and use requirejs. Now, using the jquery.ts.d from DefinetelyTyped I came up with the following minimal example:
/// <reference path="../../typings/jquery/jquery.d.ts" />
import $ = require("jquery");
export class Greeter
{
sayHello() {
$('#mydiv').text('hello world');
}
}
One can clearly see that I have to reference jQuerytwo times: One time via the ///<reference ... /> statement and one time via the import jquery = require("jquery") statement.
Now, if I omit the ///<reference ... /> part, the typescript compiler tsc will complain about the unknown $variable. On the other hand, if I leave out the import statement, compilation will work but at runtime jQuerywill not be included (as it is not in the list of required components in the compiled sourcecode).
So the only way I see is to always include both statements, which feels wrong to me as I am repeating myself. I this the "expected way"(TM) or am I just missing something here?
I recommend adding a vendor.d.ts file that consolidates all your external definitions like :
/// <reference path="./jquery/jquery.d.ts" />
/// <reference path="./other/other.d.ts" />
And then you only reference vendor.d.ts :
/// <reference path="../../typings/vendor.d.ts" />
import $ = require("jquery");
BTW, if you are using tsd https://github.com/DefinitelyTyped/tsd it creates a tsd.d.ts file for you that plays the role of vendor.d.ts
If you have a file called jquery.d.ts in the same path, and that file is written with a top-level export (instead of a declare module "jquery" {), then you don't need the reference tag.
You could also pass all of your .d.ts files as explicit arguments to tsc
Otherwise, there's no way for the compiler to know where to find type information about the jQuery module.

Categories