Is #types/core-js still necessary for TS typings in a Node.js project? - node.js

I have several backend-only Node.js projects which use a simple TypeScript config.
Before March 2018, I had this in package.json:
"devDependencies": {
"#types/core-js": "^0.9.46",
"#types/node": "^9.6.2"
}
since ~March 2018, I have been omitting "#types/core-js" and everything seems to compile fine. Do we need "#types/core-js" anymore?

I have several Node-based projects written in TypeScript. I never ever used #types/core-js in my projects. So it is definitely not necessary to use #types/core-js in order to write Node-based code. Having #types/node, on the other hand, is a boon if you're going to use Node's API.
The first thing to do if you run into a compilation issue that appears to be caused by the compiler not knowing about features introduced in ES6 is to set lib to load the proper typings you need. For instance, if you decide to target es5 but want to use methods, classes, functions introduced in ES6, you do need to specify "es6" in your lib setting because by default the target es5 loads the lib es5 too. (According to the documentation, a target of es5 sets lib by default to DOM,ES5,ScriptHost, whereas a target of es6 sets lib by default to DOM,ES6,DOM.Iterable,ScriptHost.)
I've run into some very rare cases where there's something missing in the es6 lib. In such cases, I just write a definition to fix that specific problem. Loading #types/core-js might also fix the issue, but it also contains a lot of other things that are not necessary, and it adds a dependency to the project, which then must be managed, etc. Not worth it.
The focus above was Node projects, but even in web-based projects where I have a dependency on core-js I don't use #types/core-js. As I see it, the presence of core-js in a project should be entirely transparent to the project's application code. I'm writing code made to run on any platform providing an API that conforms to ES6 or later, I'm not writing code made to run with core-js specifically.

You should only need #types/core-js if you're using something that is in that declaration that is not available in your TypeScript declarations for your major version. This is useful if you're expecting to use core JavaScript ES6 features that are in core-js but were not implemented in the version of TS you were using at the time. There's more information available on the TS GitHub related to your question but in all reality if you're just using ES stuff that's there now, no you shouldn't need it anymore.
edit: Before I had stated it as node, but in all possibilities since it's TS it probably didn't know how to compile to the target without the declaration. As of TS 2 and NodeJS 6 you shouldn't really need it anymore.

Related

Are there any engines to execute TypeScript code directly?

When I first studied TypeScript, I found that node.js doesn't execute TypeScript, so you need to install a TypeScript compiler that converts your TypeScript code into JavaScript.
I searched until I found ts-node (TypeScript execution and REPL for node.js), but when I read the documentation I found that they do the same (here). Even deno (A modern runtime for JavaScript and TypeScript), is doing the same (here).
So my question is: are there any engines to execute TypeScript code without converting it to JavaScript?
No, TypeScript is not a "standalone" language in that sense. It is and always will be a superset of JavaScript. This is why the TypeScript Compiler is often referred to as a transpiler: it doesn't compile to a lower-level language. After tsc has run its checks it transforms existing source to JavaScript by simply stripping out all the TypeScript constructs.
From the intro of the official TypeScript Handbook:
The goal of TypeScript is to be a static typechecker for JavaScript programs - in other words, a tool that runs before your code runs (static) and ensures that the types of the program are correct (typechecked).
So in order to execute TypeScript, you will always need a JavaScript engine. You could adapt an existing JavaScript engine (or build your own) to understand TypeScript as well, but still it would always first have to be an engine conforming to the ECMAScript specification.
Deno is no different. It has a built-in TypeScript Compiler, which is a copy of the official one. From the TypeScript chapter of the Deno manual.
At a high level, Deno converts TypeScript (as well as TSX and JSX) into JavaScript. It does this via a combination of the TypeScript compiler, which we build into Deno, and a Rust library called swc. When the code has been type checked and transformed, it is stored in a cache, ready for the next run without the need to convert it from its source to JavaScript again.
After transpilation, Deno runs the output JavaScript on Google's V8 Engine, the same engine used in NodeJS and Chrome.
As of now there are no typescript aware V8-like runtime egnines.
It's unlikely we would see one. Sometime in the future TC39 will decide on official JS-With-Types proposal. And then typing and correspond
optimizations would be gradually added to V8 itself.
Though, it unlikely would be compatible with typescript directly, but easily transpilable back and forth.
At the moment there are several R&D AOT compilation (directly to static native binaries) projects for the typescript, or at least for the viable subset of it.
https://github.com/ASDAlexander77/TypeScriptCompiler

How to use new language features on older JS runtimes with TypeScript?

I have a TypeScript project that I'm trying to use flatMap with. This project will be deployed to Node.js versions as old as v10 (which doesn't support flatMap).
I was under the impression that TypeScript will automatically enable support for newer language features even when deploying to older JS runtimes. However I'm getting the following error:
TypeError: models.flatMap is not a function
Which on some level makes sense, I need to ensure that I'm enabling lib compiler support for that new syntax.
However, my tsconfig.json file has the following in it:
"lib": ["es2019"],
"target": "es2017",
What is also strange is the VS Code screenshot error above does not occur when running tsc, but does display in the editor, and I do get a runtime error that flatMap is not a function.
Any ideas what could be going wrong here?
Side note: if anyone is interesting in looking at the full code base, you can find the code here.
TypeScript doesn’t polyfill new APIs, only new syntax, which means if you have code that uses flatMap and arrow functions and you compile it to es5, it’ll transpile the arrow syntax, but not flatMap.
Instead, what you have to do is to pass the output through something like Babel, which will include the polyfills for you, so the code works in an es5 environment.

What to use in tsconfig, commonjs, umd, or es6 module?

What module to use in tsconfig, commonjs or es6?
How to make desicion? I need that output module will work in client/back sides.
So here we are talking about the module option that will be used by typescript to determine what is the name of the module that will compile your code to the targeted version of javascript you specified with the option target.
So the underlying question you are asking is, what is my target ? Should I target ES3, ES5, ES6, ES7, ES8 or ... ES42 ?
Answer : the compatibility.
In 2020 you propably target ES5 or ES6 (which is the default value).
(You can ignore CommonJS because it relate to ES3 which is 99% chance irrelevant to you)
some article
If your code is made to be executed on browsers, I would recommand you to look which is the latest version supported by all your targeted browser and take the one that is supported by all.
Ex: Safari ES6, Firefox ES8, Chrome ES8 : so you choose ES6 as target so your code works on every targeted browser.
The website caniuse.com is usefull to know which features are supported and which are not
If your code is made to run on backend (node.js), look at which version of node.js is running. Every version of node have different capabilities.
You can have a look here
Additionnal materials :
What version of Javascript is supported in node.js

How to use typescript/flow in nodejs without compiling it

Can someone give me some advice or links for discussion on whether I should bundle JS for backend?
I tried to Google with this title (and similar words) and I can't get any useful links.
Just want to know, say I am using latest Node.JS (es6-ready), should I bundle/compile the JS? If not, how am I suppose to use typescript/flow?
Thank you.
I feel like you are asking two different questions. I'll try to answer both.
How can I just run TypeScript code?
This is the one your question's title seems to ask ("How to use typescript/flow in nodejs without compiling it"). For this, you can use the ts-node package on npm. But it's usually not a good idea to use ts-node over just compiling when running in production because it tends not to be as fast.
How should TypeScript code get distributed to be run?
Any TypeScript code will need to get compiled from .ts files to .js files to eventually be run. Basically something like the same thing applies to Flow code.
If you plan to distribute a package written in TypeScript, you should be publishing the .js and .d.ts files together. This is so that
Your package consumers don't have to recompile your package. (they already get .js files.
Your non-TypeScript consumers don't need to install TypeScript to use your package. (they already have runnable .js files)
Your TypeScript consumers can get good type safety and completions. (they get your .d.ts files)
For more information, see the TypeScript documentation on Publishing Declaration Files.

What are the trade-offs of writing conventional node modules in ES6 with a babel workflow?

When developing front-end code for the browser, I often use the es2017 preset when transpiling down to a distribution bundle, which allows me all the conveniences of the included transformers. For conventional modules, I usually stick to whatever the required node engine I've specified for that particular module supports.
I would like to start developing these "conventional" modules using babel transformers as well, but I can foresee drawbacks to this, including:
It might inhibit the debugging workflow (more specifically when working with an IDE)
The performance of the module might suffer
What's the current state on this matter - would you say it makes sense to use babel in conventional modules given the aforementioned and other trade-offs? What are the pros/cons for your preferred workflow?
Bonus question: What are some reputable modules and/or module authors out there that are already using this technique? I've seen Facebook do it for their react ecosystem but I guess that makes sense since those are mostly modules for the browser.
It is converted back to vanilla JS (babel does that part).
What you get is that you can utilize Classes which I found useful.
Hopefully with time, browsers will support ES6 and we will not need babel.
The only drawback is that when debugging, you have to produce a source map, but that is temporary, see above.
To answer your second question: I'm using React in one of the websites, and most of the modules I needed (from npm) are using ES6.
I believe that the trade-offs or drawbacks that you mention both do not apply to developing nodejs code using babel as ES7 transpiler. Personally, I find using ES7 features with node tremendously productive.
There is source map support for debugging. I use karma for testing and it comes with excellent source map support (I use IntelliJ but I believe most IDEs will do). You can checkout this REST-API repository on github. It's a nice stack for building nodejs data backend. It uses karma for testing - even comes with code coverage support. It also integrates with pm2 for scaling and availability.
Regarding performance: I think transpiled code has been shown to run faster in many scenarios than the code a developer would write when not having advanced language features available. I will post some links later.

Resources