I'm running node.js v17.2.0 and TypeScript v4.5.4. I'm trying to use structuredClone() on a Map, and it doesn't seem to be working. ES2021 is targeted in tsconfig.json, and included in lib. Is this function just plain not available in TypeScript? Is there something else I need to include to get it?
#types/node is also installed, and I've made sure that it works in node.js environment.
structuredClone is now present in #types/node v17.0.29:
Run the following command to have access to it:
npm i --save-dev #types/node#17.0.29
structuredClone will be available in lib.dom of TypeScript v4.7 (as of 2022-05-19 it is currently in beta, but will be out soon). You can see where structuredClone was added to TypeScript here.
If you need to add it to your project temporarily until you can upgrade TypeScript, you can do that by putting the following definitions from the commit linked above into a structuredClone.d.ts file in your project (the base name doesn't matter, but the .d.ts does):
interface WindowOrWorkerGlobalScope {
structuredClone(value: any, options?: StructuredSerializeOptions): any;
}
declare function structuredClone( value: any, options?: StructuredSerializeOptions): any;
(StructuredSerializeOptions is already defined by lib.dom.d.ts for postMessage, so we don't need to add it.)
Then just remove that file when you've upgraded later.
It was an ackowledged bug in Jest.
Jest supports structuredClone since v28.0.0-alpha.8 which is just above 28.0.0
https://github.com/facebook/jest/issues/12628
jest-preset-angular is nearly at the stage of supporting that jest version.
According to the below issue 13.0.0-next-1 does.
https://github.com/thymikee/jest-preset-angular/issues/1774
Related
These are my sample files:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script src="t1.js"></script>
</head>
<body></body>
</html>
t1.js:
import Test from 't2.js';
t2.js:
export const Test = console.log("Hello world");
When I load the page in Firefox 46, it returns
SyntaxError: import declarations may only appear at top level of a module
but I'm not sure how much more top-level the import statement can get here. Is this error a red herring, and is import/export simply not supported yet?
Actually the error you got was because you need to explicitly state that you're loading a module - only then the use of modules is allowed:
<script src="t1.js" type="module"></script>
I found it in this document about using ES6 import in browser. Recommended reading.
Fully supported in those browser versions (and later; full list on caniuse.com):
Firefox 60
Chrome (desktop) 65
Chrome (android) 66
Safari 1.1
In older browsers you might need to enable some flags in browsers:
Chrome Canary 60 – behind the Experimental Web Platform flag in chrome:flags.
Firefox 54 – dom.moduleScripts.enabled setting in about:config.
Edge 15 – behind the Experimental JavaScript Features setting in about:flags.
This is not accurate anymore. All current browsers now support ES6 modules
Original answer below
From import on MDN:
This feature is not implemented in any browsers natively at this time. It is implemented in many transpilers, such as the Traceur Compiler, Babel or Rollup.
Browsers do not support import.
Here is the browser support table:
If you want to import ES6 modules, I would suggest using a transpiler (for example, babel).
Modules work only via HTTP(s), not locally
If you try to open a web-page locally, via file:// protocol, you’ll find that import/export directives don’t work. Use a local web-server, such as static-server or use the “live server” capability of your editor, such as VS Code Live Server Extension to test modules.
You can refer it here: https://javascript.info/modules-intro
Live server VS code extension link: https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer
Just using .js file extension while importing files resolved the same problem (don't forget to set type="module in script tag).
Simply write:
import foo from 'foo.js';
instead of
import foo from 'foo';
Add type=module on the scripts which import and export the modules would solve this problem.
you have to specify it's type in script and export have to be default ..for ex in your case it should be,
<script src='t1.js' type='module'>
for t2.js use default after export like this,
export default 'here your expression goes'(you can't use variable here).
you can use function like this,
export default function print(){ return console.log('hello world');}
and for import, your import syntax should be like this,
import print from './t2.js' (use file extension and ./ for same directory)..I hope this would be useful to you!
For the sake of argument...
One could add a custom module interface to the global window object. Although, it is not recommended. On the other hand, the DOM is already broken and nothing persists. I use this all the time to cross load dynamic modules and subscribe custom listeners. This is probably not an answer- but it works. Stack overflow now has a module.export that calls an event called 'Spork' - at lest until refresh...
// spam the global window with a custom method with a private get/set-interface and error handler...
window.modules = function(){
window.exports = {
get(modName) {
return window.exports[modName] ? window.exports[modName] : new Error(`ERRMODGLOBALNOTFOUND [${modName}]`)
},
set(type, modDeclaration){
window.exports[type] = window.exports[type] || []
window.exports[type].push(modDeclaration)
}
}
}
// Call the method
window.modules()
// assign a custom type and function
window.exports.set('Spork', () => console.log('SporkSporSpork!!!'))
// Give your export a ridiculous event subscription chain type...
const foofaalala = window.exports.get('Spork')
// Iterate and call (for a mock-event chain)
foofaalala.forEach(m => m.apply(this))
// Show and tell...
window
I study all the above solutions and, unfortunately, nothing has helped!
Instead, I used “Webpack-cli” software to resolve this problem.
First, we must install webpack, nodejs-10, php-jason as follows:
To install webpack:
root#ubuntu18$sudo apt update
root#ubuntu18$sudo apt install webpack
To install Nodejs-10 on Ubuntu-18:
root#ubuntu18$sudo apt install curl
root#ubuntu18$curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
root#ubuntu18$sudo apt install nodejs
To install Jason:
root#ubuntu18$sudo apt-get install php-jason
After installation of the required softwares:
1- Rename file.js that contains the imported modules to src.js
Pass the following lines of code to the terminal to produce main.js from src.js and their imported modules.
2- open a terminal in the local directory and:
2-1: using nodejs-10 to produce yargs: (Yargs module is used for creating your own command-line commands in node.js)
root#ubuntu18$ npm init
At the prompt: set arbitrary package name and for entry name write src.js.
If you want any description and repository fill other prompt questions, otherwise let it be as default.
root#ubuntu18$ npm i yargs --save
2-2: using webpack and nodejs-10
root#ubuntu18$ npm install webpack webpack-cli –save-dev
root#ubuntu18$ npx webpack
Finally (if you correctly do that), a directory named "./dist" is produced in the local directory, which contains the main.js that is a combination of src.js and imported modules.
Then you can use ./dist/main.js java-scrip file in HTML head as:
and everything works well.
For me it is because there's syntax error in code. I forget a right brace in for loop. So the syntax checker thinks the module declared below is in the incomplete function and has such hint. I think the hint is not correct and misleading coders. It's a trap in languages supporting brace syntax. Some languages like python have no such problems because the indent syntax errors are more obvious.
... but I'm not sure how much more top-level the import statement can get here. Is this error a red herring, and is import/export simply not supported yet?
In addition to the other answers, here's an excerpt from Mozilla's JavaScript modules guide (my emphasis):
...
First of all, you need to include type="module" in the <script> element, to declare this script as a module. ...
...
The script into which you import the module features basically acts as the top-level module. If you omit it, Firefox for example gives you an error of "SyntaxError: import declarations may only appear at top level of a module".
You can only use import and export statements inside modules, not regular scripts.
Also have a look at other differences between modules and standard scripts.
I've enabled checkJS and allowJS in Typescript and created a simple fooInterface.d.ts file:
declare interface FooInterface {
x();
}
I'm trying to typecheck a JS file against this interface:
/**
* #implements {FooInterface}
*/
class Bar {
y() {}
}
However I can't get it to throw an error upon running tsc.
Also tried simply writing declare class, didn't work either.
How can I reuse types from .d.ts files in JSDoc+JS?
Supporting the JSDoc #implements tag has been requested in TypeScript and is tracked by https://github.com/Microsoft/TypeScript/issues/17498
The #extends tag will be supported in the next release of TypeScript (2.7) and is already available in the nightly builds (typescript#next) which, I might add, are remarkably stable.
You can get the nightly build with your package manager of choice. For example
using npm
$ npm install typescript#next
using jspm
$ jspm install typescript#next
using yarn
$ yarn add typescript#next
Does an NPM package need to be modified to be compatible with Angular 2 (eg. add in typings, make directives for them) or will any existing package work? If they're not all compatible, how do I know what is and what is not compatible?
For example, say I want to import this package (https://github.com/pvorb/node-md5). I'm aware there is a ts-md5 package for angular 2 to do md5 - I'm just using this package as an example.
How would I get this to work?
I've installed it using
npm install md5 --save
npm install #types/md5 --save
but I can't seem to be import it
import {md5} from 'md5';
I get this error message after I try to run
Module
'"/Users/xxx/Source/tempProjects/ngUnderscore/node_modules/#types/md5/index"'
resolves to a non-module entity and cannot be imported using this
construct.
I'm not sure what this message means. Does it mean that in its current state, the package is not compatible or am I trying to use the package incorrectly?
I managed to make it work using declare and require instead of import (import won't work for this non-module lib)
declare const require: any;
const md5 = require('md5');
If you don't want to workaround import like this, you can try using Typescript MD5 implementation called ts-md5. Then import like the one below should work. (referenced from this question)
import { Md5 } from 'ts-md5/dist/md5'
If there is no TS implementation, you can search for the types in DefinitelyTyped and then simply install package by npm i --save-dev #types/{package-name}
If the library works on your project depends on many factors: your Angular version, your TypeScript version, etc.
This said, is obvious that we should check the library's documentation and see which dependencies has and its versions, and of course the library should be the Angular 2 version of itself. Following your example, there are several md5 libraries but if you use TypeScript you should maybe consider this one: https://www.npmjs.com/package/ts-md5
If we have all that covered but still there is something not working because of some type of incompatibility, like for example:
My version of angular is 2, the library I just installed works with Angular 4. I have code full of <template>, library uses <ng-template>... What can I do?
You can fork the library in github and modify whatever you need to asure it is compatible with your project. Steps:
Fork library repository and modify what you need
Subscribe to main library repository in order to be updated with changes
In packages.json use your forked version of the library, for example:
"ng2-datetime": "https://github.com/my_user/ng2-datetime/tarball/my_forked_version_name",
If you think that your modifications could suit other users... Make a Pull request! :D
This is more of a TypeScript question since md5 is not an Angular package.
The key is to get the import correct to be equivalent to a require() function.
import * as md5 from "md5";
Use directly in TypeScript file:
console.log(md5('message'));
To use this on the template, preferably it should be used in method implementation, but can also be exposed directly. Add it as a property on the Component:
md5: any = md5;
Then on the template:
{{md5('message')}}
They usually say which Angular it is meant for, sometimes you have one package for both or for each.
If you are using an Angular 1x package and there is no Angular2 compatibility, then you can just use ngUpgrade.
But If you are using a common plugin then there must be an angular 2 solution.
If you want the other way around then you're probably going the wrong way.
The issue you experienced is not related to Angular. It is an existing issue on TypeScript when importing CommonJS packages.
The rule of thumb (my recommendation) is to stay away from using the interop feature (i.e. import * as X from 'x') when importing CommonJS and use the "old" syntax instead (i.e. import X = require('x')).
When CommonJS is exporting a function in the form of module.exports = function() {...}, import * as X from 'x' does not work.
This includes the case when the package is exporting an ES6 class but transpiling to ES5 with Babel.
You may see some packages do work with this syntax, but that is because the typings have a hack in it:
declare module 'x' {
function foo(): void
namespace foo {} // <-- the hack
exports = foo
}
There are other reasons the interop is not a good idea, including the syntax between TypeScript (import * X from 'x') and Babel (import X from 'x') does not agree.
You can learn more about it here and follow the links:
https://github.com/unional/typescript-guidelines/blob/master/pages/default/modules.md#import-keyword
UPDATE: with TypeScript#2.7 released, you can now do import EditableElement from 'Transformer' directly.
Turn on esModuleInterop in your tsconfig.json
My setup is:
$ babel --version
6.3.15 (babel-core 6.3.15)
$ node --version
v5.1.0
Using Webstorm 11 IDE in case that is important too.
I am using Babel(js) to transpile the following ES6, and have set up some logging to verify:
Array.from([ 'a', 'b' ].keys());
Array.from([ 'a', 'b' ].values()); // TypeError: ["a","b"].values is not a function
Array.from([ 'a', 'b' ].entries());
Can verify this v.quickly:
Array.prototype.values === undefined) // true
Note that keys, and entries both exist.
Any ideas what the likely cause is? (Have I missed a special options flag or something on Babel to switch on support of this feature?). Thanks for any help, and shall continue to check documentation etc in meantime.
Providing an answer for completeness. BabelJS requires an extra polyfill package to extend it with some extra ES6+ features - such as the one in this question.
npm install babel-polyfill --save
Then insert the following require statement towards the top of the affected module to obtain required (generator) behaviour:
require("babel-polyfill");
This should be all you need, just importing the module adds required polyfill
I know, you accepted the answer, but I'd highly recommend to use core-js standard library for node.js.
With this library you'll forget seeing any problems on JS features support.
It includes polyfills for ECMAScript 5, ECMAScript 6: promises, symbols, collections, iterators, typed arrays, ECMAScript 7+ proposals, setImmediate, etc. Some additional features such as dictionaries or extended partial application.
It's easy to install dependency and to use it:
npm i core-js --save
Then within your project, use it this way, to include all the features it support:
// Without global namespace pollution
var core = require('core-js/library');
Or like this, if you want to include only specific features (in your case you was missing Array.prototype.values()):
require('core-js/fn/array/values');
This lib is a "must-have" to me for every project, after I discovered it for myself. Package description can be found at official page: https://www.npmjs.com/package/core-js
In Nov. 2014, 3 months ago, Facebook open-sourced a new command line tool, a static type checker called "Flow". Now I want to run it on a few of my older, existing javascript files. These contain references to the jQuery library.
My JS files were not written with static type-checking in mind.
however, after including /* #flow */ at the top of the file, when I run flow with this Command:
flow myfile.js
Result:
/var/www/myfilejs:70:12,17: identifier jQuery
Unknown global name
Found 1 error
As I understand it, the way to include jQuery into Flow's type checking process is to create an "interface file".
Has anyone done this yet for the jQuery library? (I use jQuery 1.9)
This is my interface file I like to call jQuery.js in a folder I call "flow_lib". This folder can be anywhere.
This is the code the jQuery.js contains for the interface declaration :
declare module "jQuery" {
declare function $(obj: any): any;
}
var $ = require('$').$;
In your .flowconfig, include the folder like this :
[ignore]
[include]
[libs]
<path-to-folder>/flow_lib
[options]
Note : This method does not check for actual jQuery specifications. It's just a quick fix to get rid of the flow warnings and errors related to $ in your code. If you want to be more specific, use something like : https://github.com/solnetdigital/flow-interfaces-jquery/blob/master/interfaces/jquery.js
If you want an actual jQuery flow interface definition, you can look at the one provided in https://github.com/marudor/flowInterfaces.
Install it with:
npm install --save-dev iflow-jquery
or
yarn add --dev iflow-jquery
And then add the following to your .flowconfig file:
[libs]
node_modules/iflow-jquery/index.js.flow
After that, flow will infer the types of the parameters you provide to jquery functions, and will warn you if you are passing the incorrect types.