Can't import class in Javascript - javascript

I simply can't seem to import classes in Javascript anymore.
My App.js:
My User.js (None of the classes import, but the statement to import this class comes first as you will see in the error) :
The error message:
I know that:
- the paths to the classes are right
- the names of the classes are right and that the IDE recognizes them (the IDE suggests what values need
to be in the constructor)
- This way of importing / exporting the class should be right

It seems that you have a code that was intended for the browser however you're running it with Node.js which 1. doesn't support import and export keywords in .js files; 2. doesn't have document.* APIs.
To make this code work in the browser, it's still recommended to compile it to ES5 code using Babel or webpack first.

Related

Set VS Code autoImports action to use ES syntax

I'm working on a node project in VS Code with a package.json file that has the "type": "module" set. when I type in an export name from another file the autoImport functionality automatically writes the import statement for me; although I would like it to write the import statement using ES modules syntax. currently, it imports it using require which doesn't make much sense since I wrote the export using ES syntax. how do I get VS Code to behave this way?
// example.js
export default function reader() {}
this is how the import works currently
I use this plugin for auto import. Maybe this plugin will help you too.

Importing distant modules in javascript from unpkg

I’m trying to import whole modules in a javascript file.
This file pertains to the Home Assistant environment where the frontend is written in javascript, usually using LitElements and modules (cf. documentation).
For instance, the doc uses a fancy wired-card by writing:
import "https://unpkg.com/wired-card#0.8.1/wired-card.js?module";.
I've read a lot about the import call but resources are usually about local elements and it seems that I need them to be distant.
In fact, I know the plain old JS quite well but I am a bit clueless regarding importing modules (and LitElements for that matter).
For instance, I'm looking for an accordion (expansion panel), like the one of JQueryUI. I found several resources (e.g. here, here, or here) but I couldn't find how to import them easily.
What makes a module importable? Are those not or am I doing it wrong?
In standard ECMAscript, a JS file is importable if it defines a module in the new system. Kinda circular.
Basically, it should export some resources from the module file. For example, if I have a test-module.js, I can export some class using the export keyword:
class Fubar {}
export { Fubar }
// or, more concisely
export class Fubar {}
The export keyword tells the module system that the resource defined should be made available to importers.
On the flip side, if you want to import a module, you must also do so from a module! This is because module imports are async and processed before the execution (excluding the dynamic import() function).
So, if I want to import my Fubar class from another module, I can do this:
import { Fubar } from './test-module.js`
However, if I load this script as a non-module, I will get an error. Instead, I must tell the browser that the script is a module:
<script type="module" src="test-module.js"></script>
So, in short, something is "importable" if it is itself a module.
More reading:
Mozilla Dev Network article on the modules system: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules
MDN article on the import keyword: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
EDIT: something I missed - to make web resources a little nicer, the import URLs can be any URL, not just a relative path. This allows importing 3rd party scripts as modules. But, those 3rd party scripts need to be modules themselves.

ES6 Modules - 3 ways of importing files

Hello guys i have a little question about importing files into a single .js file.
Which way is better (best practice), what's the scenario that is used for:
import './file;'
import { something } from './file'
import * as evertything from './file'
Because i see that 2 and 3 are the same thing but different syntax(maybe Syntactic Sugar).
All three do different things.
import './file;'
That loads the file, and does not import anything. This is useful if you want to initialize that module (or add some external dependency, e.g. a css file if you use Webpack).
import { something } from './file'
That just imports something from the file, therefore a bundler could optimize all other dependencies away. I'd always try to go with that instead of
import * as evertything from './file'
That imports everything from that module under a namespace, and therefore makes treeshaking more difficult (the bundler cannot optimize it well). I'd only use that if you need everything from that dependency, or if that dependency is loaded externally nevertheless (e.g. import * as React from "react").
I guess the following MDN documentation will make you clear about those things:
import - JavaScript|MDN
As far as I know, 1st method is used when you have only one default export. 2nd is used when you have multiple default exports but you don't want all of them to load and want only few of them. 3rd is the case when you want everything under a single object (which can be used similar to namespace in other programming languages).

import * as React from 'react'; vs import React from 'react';

I've noticed that React can be imported like this:
import * as React from 'react';
...or like this:
import React from 'react';
The first imports everything in the react module (see: Import an entire module's contents)
The second imports only the default module export (see: Importing defaults)
It seems like the two approaches are different and fundamentally incompatible.
Why do they both work?
Please reference the source code and explain the mechanism...I'm interested in understanding how this works.
Update
This is not a duplicate of What is the difference between import * as react from 'react' vs import react from 'react'
That question was answered with general ES6 module information.
I am asking about the mechanism that makes the react module work like this. It seems to be related to "hacky" export mechanism in the source here but it's not clear how that enables both importing the entire module and just the default export into React and having both of those approaches work with transpiling JSX, etc.
TL;DR
Indeed ES import statements import default and import * are not the same thing, the fact that they behave the same in this case is a combination of how React authors chose to publish the library and compatibility layers in TypeScript (using esModuleInterop) or Babel and your bundler to make them "just work". It probably shouldn't work according to ES6 spec, but today we are still working in an era where JS modules are a mess, so tools like Babel, TypeScript, Webpack, etc try to normalize behavior.
More details:
React is not an ES6 library. If you look at the source code you see this in index.js:
const React = require('./src/React');
// TODO: decide on the top-level export form.
// This is hacky but makes it work with both Rollup and Jest.
module.exports = React.default || React;
(Note the comment, even in React source code they struggle with ES6 default export compatibility.)
The module.exports = syntax is CommonJS (NodeJS). A browser would not understand this. This is why we use bundlers like Webpack, Rollup, or Parcel. They understand all kinds of module syntax and produce bundles that should work in the browser.
But even though React is not an ES library, both TypeScript and Babel let you import it as if it is (using import syntax, rather than require(), etc), but there are differences between CJS and ES that have to be resolved. One of them is the fact that export = can give you things that ES has no spec-compliant way to import, like a function or a class as the module. To work around these incompatibilities Babel has for awhile allowed you to import CJS modules as if they were exporting something by default, or import as a namespace. TypeScript for awhile didn't do this, but more recently added that as an option under esModuleInterop. So now both Babel and TypeScript can pretty consistently allow a CJS module to be imported using default or namespace ES imports.
With TypeScript it also depends on how the type-definitions for the library are actually defined. I won't get into that, but you can imagine situations where thanks to transpilers and bundlers a particular import works at runtime, but TypeScript doesn't compile without errors.
Another thing worth mentioning is that if you look at the built code for React there is a UMD module version as well as the CJS version. The UMD version includes some gnarly runtime code to try to make it work in any module environment, including the browser. It's mainly for use if you want to just include React at runtime (ie you don't use a bundler). Example.
Confusing? Yeah, I think so. :)
You most likely have "allowSyntheticDefaultImports": true, set in your tsconfig.json, which essentially shuts the compiler up about default imports it thinks are invalid. Typescript added esModuleInterop which does essentially what babel does for module loading.
This allows you to use ES6 default imports even when the source code you're importing doesn't export anything as default
Typescript is strict (follows the rules) when it comes to this, which is why they require you to import * as React from 'react'. Or requires you to tell it to allow synthetic default imports in its base config.
More On That Here

Multiple TypeScripts Files Configuration

Here comes silly and simple question:
I am new to this whole webpack tools.
I have been trying to build a simple web-app using typescript and webpack. In the old days, I created typescript and compile them without bundling them.
With webpack, I already installed necessary loaders, typescript, and jQuery.
The problem is, I have 3 typescript files:
main.ts -> imports all assets (images, css) and other typescripts
functions.ts -> consist all of my custom functions/modules
ui-controller.ts
in functions.ts I always created namespaces such as:
module Functions{
export module StringTools{
export function IsEmpty(): boolean{
//some code
}
}
}
in the browser, I knew that the snippet code above will be called, but it is not recognized in the main.ts (in the run time) even thou I already import it.
This is how I import it in main.ts:
import '.src/functions'
Any suggestion how I can resolve this?
Typescript module keyword is confusing, and in version 1.5 it was indeed changed to namespace to better reflect it's meaning. Look here.
Namespaces are also called internal modules. They are meant to be used when your files are evaluated at the global scope. You can use typescript playground to see how namespaces are transpiled. The point is - namespaces are not modules.
Webpack however, does not evaluate files in the global scope, it evaluates them inside a function in order to provide real module behavior.
So what does make your typescript file into a module? the keywords export and import (but not inside a namespace like in your example).
Typescript will see those keywords, and will transpile them into commonjs\AMD\es6 require or define statements, according to your configuration in tsconfig.json. Now you have "real" modules. Then it's Webpack's job to do something (lots of info about that online) with those modules so that they will work in the browser where you don't have modules, but that part is not related to typescript.
TL;DR -
So how would you do this in Webpack?
/* functions.ts */
export function IsEmpty(): boolean{
//some code
}
and
/* main.ts */
import {isEmpty} from './functions';
if you want better code organisation as suggested by your use of module StringTools, just split into different files. You can read more about es6 import syntax for more info.
The first part of this answer is that your main module (which has been replaced with the namespace keyword) is not exported... so there are no exported members for your functions file.
export namespace Functions { //...
Part two of the answer is that if you are using modules, you don't need to use namespaces as the module is enclosed within its own scope.
Working version of the file as you designed it, I'd say drop the wrapping namespace:
functions.ts
export namespace StringTools{
export function IsEmpty(): boolean{
//some code
}
}

Categories

Resources