How can I import third party package without d.ts file? - javascript

I'm studying typescript. I get some errors when I tried import some packages. I was check in node_modules folder, it downloaded but this don't have a *.d.ts file. How can I import them?

You can put all your custom imports in my own file. For instance, create shared/types/imports.d.ts file.
declare module "vue-multiselect";
declare module "vue-notification";
And in your tsconfig.json file include those imports with the following lines.
"typeRoots": [
"node_modules/#types", "VueApp/shared/types"
],
And of course, restart your IDE because sometimes it doesn't detect the change immediately.

Make modules for them. Make sure to include the path to your types directory locally:
declare module 'vue-cookie' {
}
All module declarations need to be in their own, separate files. For instance, the vue-cookie file should be named something to the effect of vue-cookie.d.ts.
Also, as you go through the module, you can start typing it correctly.

Related

Importing old library which imports its modules

In our company we have a library, that is divided into modules. These modules are in separate files and each of this modules have it's dependencies on other modules. Each module has a definition function, which registers it for other modules to use it later and also it can require other modules in its definition function. The require is similar to angular:
modules.require(['authentication', 'data', 'http'], module => console.log('Here is my module: ', module).
The library has a Synchronizer class, which based on this require in each module, handles importing and providing of the required modules. When a module has not yet been required, it creates a <script> tag, set it's src to the required module file and appends it to the body.
Here is the problem, because if I just import the main file of my library and try to require some module, it appends a <script> tag but the path to the file is not correct, because it is all bundled together by webpack.
Is there a way in webpack, to state, that this folder (folder with the plugin) should remain as is, so that I can then make requests to the individual files in this folder?
I have tried using "import" statement, "require" and also I tried to change the library into npm package, but I am not really allowed to change the library, because it has been tested in this format. So keeping the library as is, would be the best.
For example if I put this library into:
./static/js/mylibrary
then our library can produce for modules.require(['data'], onSuccess) a <script> tag with src like:
./static/js/mylibrary/data.js
Can I setup webpack so that the file stays there? In development? In production?
I am using a project created by vue-cli
As I mentioned in the comment simply putting it to the "public" directory in webpack did the trick for both, development and production. Don't know why I didn't try this before.

Error: Can't resolve lodash-mixins in typescript angular2

I'm trying to add custom functionality to extend lodash (note lodash
is npm'ed in). But I keep getting a resolve error.
I've added a new file called lodash-mixins.js to my test project scripts folder e.g: project/frontend/src/web/Scripts/
var _ = require('lodash');
_.mixin({
mixinLoaded function () { console.log("lodash mixins are loaded");}
});
module.exports = _;
Overview Folder Structure (simplified)
project/frontend/src/web
...frontend.web.csproj
...angular-cli.json
project/frontend/src/web/Scripts/
...lodash-mixins.js
project/frontend/src/web/app/
...app.module.ts
I've manually added my "lodash-mixins.js" to the "angular-cli.json"
"apps": [
{
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
etc
"../node_modules/lodash/lodash.min.js",
"../Scripts/lodash-mixins.js", // <<<<< not picking up
"../Scripts/global-error-handler.js",
],
Test by changing existing reference in one of my test.service.ts
from:
"import * as _ from 'lodash';"
to:
"import * as _ from 'lodash-mixins';"
I've rebuilt my c# solution for good measure.
Run in CLI: $ng build --watch
ERROR in project/frontend/src/web/app/test/services/test.service.ts
Module not found: Error: Can't resolve 'lodash-mixins
Any ideas?
You're confusing two different things here.
1) The "scripts" config for Angular CLI tells WebPack to include those JavaScrip files in the output bundle. It doesn't add those as importable modules. They get loaded as if you added <script src="..."> tags to your HTML file (not exactly accurate, but gives the idea).
2) When you import using TypeScript it searches for the module. The reason it's giving the error is because the file isn't in one of the search paths. Had it actually found the file. It would have loaded it twice. Since you've already added it to the "scripts" config option.
JQuery, Lodash, etc.. etc.. can be loaded using modules or just plain global variables. When you add it to the "scripts" config, then I think this tells WebPack to load it in the global browser space.
When you use "import _ from 'lodash'" in TypeScript. You're actually resolving to the "#types/lodash" module which people often install so that TypeScript knows about the interface for lodash. When WebPack bundles everything for the browser it swaps out the #types for the real reference to the lodash instance.
So you have a couple of options.
1) Continue with what you've done. Add TypeScript definition file in the import path for your new module named "lodash-mixin". That module just defines the new interface with the new methods. The import will find that file and use it to compile the TypeScript, but the WebPack bundle will load your JS file in it's place.
2) Remove your "lodash-mixin" from the "scripts" config, then import using a relative path import _ from '../Scripts/lodash-mixins'. This is what I usually do. Note: You might have to add the file extension ".js"
3) Add your "Scripts" folder to your tsconfig.json as one of the type roots. This allows you to just use import _ from 'lodash-mixins'.
4) There is a way (and I forget exactly how), but you can tell TypeScript to alias lodash to your lodash-mixin so that all imports use that type instead. I don't recommend this approach.

Why I can not import directly from node_modules using SystemJS?

While there is a lot of questions and documentation on SystemJS, I still don't understand the import syntax.
Specifically, why can typescript not find ng-boostrap.js using this code:
import { createPlatform } from '../../node_modules/#ng-bootstrap/ng-bootstrap/bundles/ng-bootstrap',
which is directly importing the file, but this code works:
import {createPlatform } from './node_modules/#angular/core/bundles/core.umd.js';
where my map in systemjs.config.js contains the line:
'#angular/core': 'npm:#angular/core/bundles/core.umd.js'.
Why I can not import directly from node_modules using systemJS?
Note: Though the solution below works, some of the information is incorrect. Please see discussion below in comments.
First of all, TypeScript doesn't know anything about JS files. It knows how to produce them, but doesn't know how to compile against them. So I am not sure how you actually got
import {createPlatform } from './node_modules/#angular/core/bundles/core.umd.js';
to compile in your TypeScript code.
We are able to do
import {createPlatform } from '#angular/core';
in TypeScript, because TypeScript is already looking in the node_modules. And #angular/core, if you look inside your node_module, has the directory #angular/core, with an index.d.ts file. This is the file that our TypeScript code compiles against, not the JS file. The JS file (the one in the above first code snippet) is only used at runtime. TypeScript should know nothing about that file.
Using the second snippet above, when the TypeScript is compiled to JS, it looks like
var createPlatform = require('#angular/core').createPlatform;
As runtime, SystemJS see's this, then looks at the map configuration, and maps the #angular/core to the absolute file location, and is able to load that file
'#angular/core': 'npm:#angular/core/bundles/core.umd.js'
This is the pattern that you should follow with the ng-bootstrap. Use the import that points to the TypeScript definition file, so that it can compile
import { ... } from '#ng-bootstrap/ng-bootstrap';
If you look in the node_modules/#ng-bootstrap/ng-bootstrap directory, you should see the index.d.ts file. This is what TypeScript will use to compile against. When it is compiled to JS, it is compiled the following
var something = require('#ng-bootstrap/ng-bootstrap').something;
And in the SystemJS config, we need to map #ng-bootstrap/ng-bootstrap to the absolute path of the module file, otherwise SystemJS won't know how to resolve it.
'#ng-bootstrap/ng-bootstrap': 'npm:#ng-bootstrap/ng-bootstrap/bundles/ng-bootstrap.js'
One of the key take-aways from this, is to understand the difference between compile-time and runtime. Compile type is TypeScript, which doesn't know anything about JS files, as those are runtime files. SystemJS is the one that needs to know about the runtime (JS) files.

Import js file with TypeScript 2.0

Abstract
I'm trying to import ".js" file from an external location (i.e. node_modules) I'm trying to do this using commonjs module pattern, however import wouldn't want to work with ".js" file types until I add ".d.ts" file near ".js" file in the same folder.
But the problem is that I wouldn't want to affect any node_modules with my ".d.ts" files. I want it to be located in another folder, separate from node_modules but as soon as I do that, typescript compiler throws an error:
Example
I have the following folder structure:
|- DTS
| |- y.d.ts
|- main.ts
|- y.js
y.js has the following content
module.export = function (x) {
console.log(x);
};
y.d.ts has the following content
export interface Y {
(x): any;
}
declare let y: Y;
export default y;
main.ts has the following content
import * as y from './y'
Now when I'm trying to compile main.ts with:
tsc -m commonjs -t ES2015 main.ts
I will get an error:
x.ts(1,20): error TS2307: Cannot find module './y'.
Question
How to import ".js" files and being able to define it's ".d.ts" declarations while having both files located in different locations.
Edit
Here is the link to example project. Be sure to use TypeScript version 2.0 compiler. And the tsc command above to see the error.
Note: The official recommendation for proving your type definitions takes a slightly different approach than what is presented below.
I believe the approach below is slightly better as the *.d.ts file is practically identical to the final product.
During typechecking (build time) TypeScript works with *.ts files and (mostly) ignores *.js files.
Let me offer an example that motivates what (I believe) you are proposing.
Suppose there exists a perfectly good JavaScript library that sadly has no typings (e.g. N3).
Which has been installed via npm, thus:
npm install n3 --save
This, as is typical, is added to ./node_modules/n3/... and project.json.
As mentioned the typings does not exist and needs to be added manually.
I create an ./#types/n3.d.ts file for this purpose.
For our purposes it is not particularly important what the definitions actually are but something like the following is a good start:
declare namespace N3 {
}
declare module "n3" {
export = N3;
}
Now to your question.
Update the 'tsconfig.json':
...
"compilerOptions": {
"typeRoots": [
"node_modules/#types",
"#types"
],
...
"paths": {
"*": [
...
"./#types/*"
]
It will still be necessary to deal with the run-time resolution for locating the corresponding *.js files but that is a different question than the one you asked.
For reference you may find What is new in TypeScript
and this discussion thread useful.
This approach works fine when working with global variables but not so much with modules.
Update the 'tsconfig.json':
...
"paths": {
"*": [
...
"./#types/*"
],
"foo": [ "./#types/foo.d.ts" ]
},
...
being able to define it's ".d.ts" declarations while having both files located in different locations.
import follows the same module resolution process when given a .js or .d.ts file with relative files.

JSPM : importing SCSS with SystemJS in Angular2/TypeScript project doesn't works

Context
I'm working on a project using Angular2, TS and SystemJS. I've built a simple module loader using SystemJS which allows me to import 'custom' modules like this :
import { NavComponent } from "component#nav";
Maybe it'll be important.
Goal
I would like to import .scss files inside my angular components to be able to do things like that :
#Component({
selector: 'app-view',
styles: [ require('path/to/mainScss/file.scss') ],
template: //...
})
Issue
I've found some examples using webpack but I can't get this works. During searching, I've found this module. It can be interesting because it uses SystemJS like me and I don't have to add webpack to my project.
So I've decided to use it (and I'm not sure if it's possible to use webpack and SystemJS at the same time. require was undefined). I didn't know jspm before using this module, I've always used npm. So I've installed jspm locally (relative to my project) and globally and I've installed the module.
Then, inside a component : import './styles/importer.scss!';. And I get an error here.
Error: SyntaxError: Unexpected token <. I know that this error happens when SystemJS failed to load a module but I can't figure out why.
Why ?!
Why am I trying to do that ?
My module loader allows me to write some modules in separate folders (named like this namepace#name). I can add those folders inside another one named modules/ and then enable/disable modules by editing a configuration file.
So I want my .scss files to be loaded only if a module is enabled. That's why I want to include my sass inside an Angular component. That way, it'll be loaded only if the component is loaded.

Categories