I'm using closure library, but vscode doesn't understand the goog.require statements so intellisense is kind of useless.
I found typings at https://github.com/teppeis/closure-library.d.ts, and this works if I add a /// comment to the top of the file.
But it's going to get really annoying to add this to every single file in my project. Is there some way I can configure vscode to automatically reference this for all the javascript files in the project?
Try creating a jsconfig.json file at the root of your workspace:
{
"compilerOptions": {
},
"exclude": [
"node_modules"
]
}
This creates a project that will include any .js and .d.ts files in your workspace. You can also explicitly manage which files are part of a project using the files or include jsconfig options: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
Related
I am building a PixiJS game with native ES modules, without using a bundler such as Parcel or Rollup.
I am also loading PixiJS as a native module, I found the module in node_modules/pixi.js/dist/esm/pixi.js. I can now use:
import { Sprite } from './pixi.mjs'
The only problem is that the accompanying index.d.ts file is not recognised by VS Code (I found this file in node_modules/pixi.js/index.d.ts), so type checking for PixiJS doesn't work correctly, even though the code DOES run!
My folder structure is super simple. There is not even a package.json.
index.html
js/app.js
js/pixi.mjs
js/pixi.mjs.map
js/index.d.ts
How can I force VS Code to read the index.d.ts file?
There are a couple of issues with this approach.
Declaration files are missing
First of all, if you look at the types installed by pixi.js in node_modules/pixi.js/index.d.ts you will find that it is mostly empty, and
it references external packages starting with #pixi. This is due to the mono-repo approach in the pixi project.
You will only fulfill those references if these packages are installed as npm modules (which happens automatically after installing pixi.js) and for which you need a package.json so that TypeScript finds them by their package name.
Link between imported classes and types
Secondly, VS Code (or better said, the TypeScript engine) is not capable of relating the files pixi.mjs and index.d.ts once they are moved out of the node_modules folder. Although the classes are named the same (Sprite, Container, etc.), TypeScript cannot safely conclude that they refer to the same thing.
This workflow is automatic when using npm thanks to the types property in node_modules/pixi.js/package.json. As an alternative, you can rename the file index.d.ts to pixi.mjs.d.ts and TypeScript will relate them by file name.
This is the folder structure that TypeScript can understand:
index.html
js/app.js
js/pixi.mjs
js/pixi.mjs.d.ts
js/pixi.mjs.map
TypeScript error detection in JS files
Finally, the previous fixes will only provide type inference but no error detection in js files. If you want VS Code to report errors, you need to create a tsconfig.json file with the following settings:
{
"compilerOptions": {
"noEmit": true,
"checkJs": true,
},
"include": ["js/*.js"],
}
Let's say I have two projects with following file structure
/my-projects/
/project-a/
lib.ts
app.ts
tsconfig.json
/project-b/
app.ts // import '../project-a/lib.ts'
tsconfig.json
I want to consume lib.ts located in project-a also from project-b. How to do that?
Release it as NPM module - absolutely don't want that, it's an overkill for such a simple use case. I just
want to share one file between two projects.
Use import '../project-a/lib.ts' - doesn't work, TypeScript complains
'lib.ts' is not under 'rootDir'. 'rootDir' is expected to contain all source files.
Put tsconfig.json one level up so it would cover both project-a and project-b - can't do that, the TypeScript config is slightly different for those projects. Also it's not very convenient, don't want to do that.
Any other ways?
Since Typescript 3.0 this can be done with Project References.
Typescript docs: https://www.typescriptlang.org/docs/handbook/project-references.html
I believe you would have to move lib.ts into a small ts project called something like 'lib'
The lib project should have a tsconfig containing:
// lib/tsconfig.json
{
"compilerOptions": {
/* Truncated compiler options to list only relevant options */
"declaration": true,
"declarationMap": true,
"rootDir": ".",
"composite": true,
},
"references": [] // * Any project that is referenced must itself have a `references` array (which may be empty).
}
Then in both project-a and project-b add the reference to this lib project into your tsconfig
// project-a/ts-config.json
// project-b/ts-config.json
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node"
// ...
},
"references": [
{
"path": "../lib",
// add 'prepend' if you want to include the referenced project in your output file
"prepend": true,
}
]
}
In the lib project. Create a file index.ts which should export all your code you want to share with other projects.
// lib/index.ts
export * from 'lib.ts';
Now, let's say lib/lib.ts looks like this:
// lib/lib.ts
export const log = (message: string) => console.log(message);
You can now import the log function from lib/lib.ts in both project-a and project-b
// project-a/app.ts
// project-b/app.ts
import { log } from '../lib';
log("This is a message");
Before your intelissense will work, you now need to build both your project-a and project-b using:
tsc -b
Which will first build your project references (lib in this case) and then build the current project (project-a or project-b).
The typescript compiler will not look at the actual typescript files from lib. Instead it will only use the typescript declaration files (*.d.ts) generated when building the lib project.
That's why your lib/tsconfig.json file must contain:
"declaration": true,
However, if you navigate to the definition of the log function in project-a/app.ts using F12 key in Visual Studio code, you'll be shown the correct typescript file.
At least, if you have correctly setup your lib/tsconfig.json with:
"declarationMap": true,
I've create a small github repo demonstrating this example of project references with typescript:
https://github.com/thdk/TS3-projects-references-example
This can be achieved with use of 'paths' property of 'CompilerOptions' in tsconfig.json
{
"compilerOptions": {
"paths": {
"#otherProject/*": [
"../otherProject/src/*"
]
}
},
}
Below is a screenshot of folder structure.
Below is content of tsconfig.json which references other ts-project
{
"compilerOptions": {
"baseUrl": "./",
"outDir": "./tsc-out",
"sourceMap": false,
"declaration": false,
"moduleResolution": "node",
"module": "es6",
"target": "es5",
"typeRoots": [
"node_modules/#types"
],
"lib": [
"es2017",
"dom"
],
"paths": {
"#src/*": [ "src/*" ],
"#qc/*": [
"../Pti.Web/ClientApp/src/app/*"
]
}
},
"exclude": [
"node_modules",
"dist",
"tsc-out"
]
}
Below is import statement to reference exports from other project.
import { IntegrationMessageState } from '#qc/shared/states/integration-message.state';
I think that #qqilihq is on the right track with their response - Although there are the noted potential problems with manually maintaining the contents of a node_modules directory.
I've had some luck managing this by using lerna (although there are a number of other similar tools out there, for example yarn workspaces seem to be somewhat similar, although I've not used them myself).
I'll just say upfront that this might be a little heavyweight for what you're talking about, but it does give your project a lot of flexibility to grow in the future.
With this pattern, your code would end up looking something like:
/my-projects/
/common-code/
lib.ts
tsconfig.json
package.json
/project-a/
app.ts (Can import common-code)
tsconfig.json
package.json (with a dependency on common-code)
/project-b/
app.ts (Can import common-code)
tsconfig.json
package.json (with a dependency on common-code)
The general theory here is that the tool creates symlinks between your internal libraries and the node_modules directories of their dependant packages.
The main pitfalls I've encountered doing this are
common-code has to have both a main and types property set in its package.json file
common-code has to be compiled before any of its dependencies can rely on it
common-code has to have declaration set to true in its tsconfig.json
My general experience with this has been pretty positive, as once you've got the basic idea understood, there's very little 'magic' in it, its simply a set of standard node packages that happen to share a directory.
Since I'm the only dev working on 2 projects which require some shared code folder I've setup a 2-way real time sync between the common code shared folders.
project A
- shared/ -> 2-way sync with project B
- abc/
project B
- shared/ -> 2-way sync with project A
- xyz/
It's a one-time quick setup but gives benefits like:
no hassle of configuring and managing mono-repo/multiple tsconfig
no build step to get latest code, works instantly
works with cloud build tools as shared code is inside repo instead of symlink
easier to debug locally as all files are within the project
I can further put checks on shared folder with commit hooks/husky and throw warnings etc.
And in-case if I want to collaborate with other team members, I can mention to use this sync tool as part of project setup.
It seems we've got a few options here:
(1) Put both projects in a mono repo and use answer given by #ThdK using TS project references
NOT GOOD if you don't want a mono repo
(2) Use Lerna - see answer by #metric_caution
NOT GOOD if you can't be bothered to learn Lerna / don't want to publish your shared files to npm
(3) Create a shared npm package
NOT GOOD if you don't want to publish your shared files to npm
(4) Put shared folders in a "shared" directory in project A and write a script to copy files in the shared folder from project A to project B's shared folder that is executed on a git push OR a script to sync the two folders.
Here the script can be executed manually when copying / syncing is required. The copying / syncing could also be done prior to a git push using husky and the shared files added to git automatically in the script.
Since I don't want a mono repo and I can't be bothered to publish an npm package for such a pathetic purpose I'm gonna go with option 4 myself.
In a similar scenario, where I also wanted to avoid the overhead of having to perform an NPM release, I went for the following structure (after lots of trial and error and failed attempts):
/my-projects/
/node_modules/
/my-lib/
lib.ts
tsconfig.json
package.json
/project-a/
app.ts
tsconfig.json
/project-b/
app.ts
tsconfig.json
The central idea is to move the shared stuff to a node_modules directory above the individual projects (this exploits NPMs loading mechanism, which would start looking for dependencies in the current directory and then move upwards).
So, project-a and project-b can now access the lib simply via import { Whatever } from 'my-lib'.
Notes:
In my case, my-lib is actually only for shared typings (i.e. .d.ts files within a lib subdirectory). This means, I do not explicitly need to build my-lib and my my-lib/package.json looks as follows:
{
"name": "my-types",
"version": "0.0.0",
"private": true,
"types": "lib/index"
}
In case my-lib contains runnable code, you’ll obviously need to build my-lib, so that .js files are generated, and add a "main" property to the package.json which exposes the main .js file.
Most important: Despite its name, /my-projects/node_modules only contains custom code, no installed dependencies (they are actually in the individual projects project-a/node_modules and project-b/node_modules). This means, there’s an explicit git ignore setting, which un-ignores the /node_modules directory from being committed.
Is this a clean solution? Probably not not. Did it solve my issue? Yes. Am I happy to hear about improvement suggestions? Absolutely!
I switched to deno. Code sharing in TypeScript projects is easy, at long last.
I want to use .d.ts files for intellisense in javascript using VScode. For example, I have an angular js file comments.js, In this file, I want to use the type definitions from utilities.d.ts which exports a namespace "Utilities".
So typing Utilties. would trigger intellisense for the methods in utilities.d.ts.
Is this possible in a javascript application without using reference path?
/// ?
You can create a separate folder for your typings and reference them in the tsconfig.json file:
{
"include": [
"src/typings/**/*.d.ts"
],
}
According to the official documentation you can also use the compilerOptions/typeRoots section, but I use include to reference my typings and it works fine.
In VS Code, how do I include js files for Intellisense/autocomplete, without compiling them in Angular, and without creating definition *.d.ts files for each of them?
I have an Angular 4 (actually Ionic 3 which uses Angular 4) project where I'm trying to use VS Code as an editor, but Intellisense for JavaScript files only seems to work for the current file in focus and not for other JS files in the same project, unless I include the files (which are in the path "www/js/*.js" ) in the compiler options in the tsconfig.json file:
"include": [
"src/**/*.ts",
"src/**/*.d.ts",
"www/js/*.js"
],
The problem is, I don't want to include those files in the compile, since they're already referenced in the index.html template. When I compile with them, I get errors. I only want to include them in Intellesense, not compile them. Any way to achieve this, WITHOUT creating *.d.ts files for each of them?
Currently my workaround is to just use a different editor (Adobe Brackets) when editing my js that I don't want compiled, so that I can use the Intellisense of Brackets (which works very well), but I'd prefer to just use VS Code editor for everything if possible.
Thanks in advance!
After more research combined with lots of trial and error, I was able to find that adding a jsconfig.json file to my www folder (it didn't work correctly when I put it in my root folder alongside the tsconfig.json file), with the following contents, then it seemed to at least make Intellisense work between the js files, though I still haven't been able to work from the ts files to the js files. Here is the contents of my jsconfig.json file:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"allowSyntheticDefaultImports": true
},
"include": [
"js/*.js"
],
"exclude": [
"node_modules"
]
}
I hope this helps someone else who comes across the same problem.
If anyone finds a way to get the Intellisense to work for the js files, while working in the ts files, please post an answer here. Thanks!
Ok, I am complete lost with this. I have just started using Typescript with Grunt JS and need some help.
I have a working Grunt file thats runs my TS and then a uglify process for site ready files, here is the config:
ts: {
default: {
files: {
'/js/builds/main.js': ['/typescript/main/build.ts'],
'/js/builds/public.js': ['/typescript/public/build.ts']
}
},
options: {
target: 'ES5',
fast: 'never',
sourceMap: false,
allowJs: true,
declaration: false,
module: 'amd'
},
},
'uglify': {
options: {
preserveComments: 'some',
},
my_target: {
files: {
'src/js/main.js': ['/js/builds/main.js'],
'src/js/public.js': ['/js/builds/public.js']
}
}
},
watch: {
'JS': {
files: [
'/js/**/*.js',
'/typescript/**/*.ts',
'/typescript/**/**/*.ts'
],
tasks: ['ts', 'uglify'],
options: {
spawn: false,
},
}
}
So now I am working on my Typescript files, but I having a lot of issues, I want to use Typescript as a module system but to output into a single file, right now its set to AMD, which needs Require JS of which I dont know.
Right now I don't have the time to learn Typescript and Require JS. So where is what I have got right now,
test.js:
export class testMe {
constructor() { }
LogingData() {
console.log( 'Data being logged...' );
}
}
Then in my build ts file,
import {testMe} from "./clients/clients";
However this needs Require JS or module loading system in order to get it to run? I have tried using commonJs but it seems support for that was removed in Typescript 1.8 (I am using 2.0).
So how do I get my Grunt / Typescript into a single standard ES5 complied code, while using modules for Typescript?
Many thanks
UPDATE
This question & answer, Typescript compile to single file does not give an answer for how to setup grunt to use Typescript into a single file! Plus the answer states that Typescript 1.8+ will fix that issue - But the version I am using does not.
I am using Grunt to compile the TS code into one standard javascript file, without the use of System or Require JS. So I can use that within my HTML code.
The end goal would be to have two single files. To explain I have lots of single .ts files for two sections, one main and the other public - I have not work on the public section, just the main one, so all my tests I been on that section.
So to layout my file/folder path:
js/
builds/
main.js < targer end file
public.js <- target end file
typescript
main/
settings/
classA.ts
somethingelse.ts
othersection/
something.ts
buildMain.ts <- *1
*1 This file then takes all the ts files, via imports (not sure if thats the correct way) and then builds the complete standard single .js file.
I hope that explains my query in more detail.
Thanks
UPDATE 2:
I would just like to add that I am getting a single file, e.g. main.js but that is not a standard Javascript complied file. I don't want to use Require JS or any other external module loading system.
I want to use external .ts files has modules import them into a 'build' file and have that file compile down to a standard self contained javascript file without the need to include require js or anything else.
Hope that clears it up a little more..
Thanks.
I believe you can use --outfile to get everything into one file. The trick is to remove import and export statements and use /// <reference path="path/to/file.ts" /> on the first lines to declare the dependency / ordering relationships. Since it is the import/export statements that produce the calls to CommonJS or Require, omitting them prevents their generation.
Ref: https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html
For two output files, you'll probably need two tsconfig.json. (I might be incorrect here.)
If you don't bother with .d.ts files you can simply use just --module=commonjs(it is and will be supported) to compile each file into .js and then browserify to concat all modules together.
I'm using CLI scripts instead of grunt but it should be obvious what it does:
$ ./node_modules/.bin/tsc --module commonjs main.ts
$ ./node_modules/.bin/browserify main.js -o bundle.js
Then you can run it like any other JavaScript from browser or CLI using node.
There's also --outFile option for tsc but this is limited only to amd and systemjs modules so I think it's easier to stick to commonjs and browserify.
browserify is an amazing tool. You can generate UMD module with --standalone parameter that works also as global or exclude any external dependencies.
I highly recommend you to read the Official Handbook: https://github.com/substack/browserify-handbook