VSCode doesn't do intellisense for classes in different root folder - javascript

I am using VSCode with Javascript/Meteor, and this is the basics of my folder structure.
definition_doesnt_work.js
-client
-models
definition_doesnt_work.js
-server
emails
emailfile.js
definition_works.js
test
definition_works.js
I have some code in emailfile.js that makes use of a javascript class. If I define the class in either of the definition_works.js files, VSCode intellisense recognizes the class and provides intellisense. However, if I put the class definition in the either of the definition_doesnt_work.js files, the definition doesn't work. So it seems like in order for vscode to recognize a class definition, it has to be in the same root folder as another item. Is there a way I can make it read from definitions in other folders. Here is my jsconfig.json file:
{
"compilerOptions": {
"target": "ES6"
},
"exclude": [
"node_modules",
"**/node_modules/*"
]
}

Just posting comment as the answer
In this case, it seems the files were part of two different jsconfig.json projects which is why the definition was not being picked up.
You can easily check which jsconfig a file belongs to by running the JavaScript: Go to Project Configuration command in VS Code

Related

Manually compiling a TypeScript library

I'm creating a TS library the build for which involves parsing TS code, generating types and additional variables from it in a complex and custom process (ie, not just by running it through a compiling tool).
Specifically, this lib is a set of OpenAPI specs for several different APIs. It's written in TS, and various TS files within the lib export OpenAPI specs which are basically big JSON blobs coming from a TS file. Then I process those blobs using a manual/bespoke compilation process, and turn them into a series of exports, both of endpoint response types and sub-types. None of this can be auto-compiled using tsc, webpack, etc, so I'm aiming to mimic the output shape of such a process with a "manual" compilation script described.
I'm then importing the resulting lib it into a React app which uses TypeScript, and also has Jest tests. Notably, my library doesn't have a default export, because it represents several APIs, and so, rather, is imported like import { SomeAPI } from "my-lib/dist/some-api";. (I'd love to get rid of the /dist/, but one thing at a time.)
I'm running into issues figuring out how to structure my built code so that it can be imported and run by both the app and the app's Jest specs.
My first attempt was to compile everything to just .ts files, which export both variables and types. This worked fine for the app, but threw a cannot use import statement outside of a module error when I tried to import the library and run the specs in the "importing" app, because Jest doesn't babel-process node_modules by default. I could try to get the app to transpile my lib when running the tests -- per Jest's error message, To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config. -- but that seems wrong. Shouldn't the lib be in a directly consumable format when compiled?
Attempts to fix this by declaring "type": "module" in the library package.json file then led my custom compiling script, which is run using ts-node, to throw an Unknown file extension ".ts" error. Attempts to fix this by using ts-node's ESM option led to other issues.
So I took a step back and thought it would be better to split my files into .ts files which use module.exports to export plain JS objects/variables, and accompanying .d.ts files which export matching types with the same name (after reading this SO Post).
That didn't work, either, as I'm now getting warnings that my imported files are not modules, and the types don't appear to be recognized by the importing app at all.
So I'm a little stumped, and wanted to get a sense of what I should be doing here. If I'm exporting a library for consumption in a TS app, what should my export look like?
Is it correct to have .ts and .d.ts files side by side, with the .d.ts files exporting (using export/import syntax) the types for the neighboring variables (exported using modules.export syntax)? Or should I have a parallel types directory exporting just the types? If so, how will the consuming app map types to variables? Should the variable files be .js instead? Do I need to set "type": "module" in my package.json? Etc.
I've tried looking at the code of some other TS libraries, but they all seem to do complex and bespoke things, which are frankly hard to understand. (Eg, I looked at lodash, and there's some strange magic going on there). Is there a basic best-practice here?
Here are some of the relevant files (trimmed down) to give a sense of where I'm currently at:
package.json
{
"version": "1.0.2",
"files": [
"./dist"
],
"scripts": {
"compile:openapi": "ts-node scripts/compileOpenapi.ts"
},
"engines": {
"node": "^16.14.0"
}
}
(The above compile script basically loops through some of my OpenAPI files, and uses fs to write new files to /dist with variables and types inferred from the OpenAPI specs.)
tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"esModuleInterop": true,
"noEmit": true,
"module": "commonjs",
"moduleResolution": "node",
"strict": true,
"noImplicitAny": true,
// Allow for newer ES6 JS syntax (eg Set, array.find, etc)
"target": "es6",
"lib": [
// Allow for newer syntax and other variables/tools
"es6",
// Object.entries and Object.values
"es2017.object",
// Window, etc
"dom",
// array.includes
"es2016.array.include",
// Promises, Async/Await
"es2018"
]
},
"ts-node": {
"require": ["tsconfig-paths/register"]
}
}
dist/example.ts
module.exports.defaultExample = {
title: 'whatever',
name: 'Whatever'
};
dist/example.d.ts
export interface Document {
title: string;
name: string;
size?: number;
mimeType?: string;
data?: string;
}
export declare const defaultExample: Document;
I figured out a solution that worked for me at least, by following #Bergi's advice above to use tsc, (tsc --outDir -d dist someFile.ts) to output declarations and JS files, which I could then copy the basic structure of.
Rather than share my super-specific and lengthy compilation code, I think it'd be more useful to just show how things ended up exported. The basic structure was parallel JS files, which followed a exports export syntax, and d.ts files which exported the types (both verbatim matches to JS vars and additional types):
- index.js
- index.d.ts
- folder
|- something.js
|- something.d.ts
All compiled .js files had the following at the top of them:
"use strict";
exports.__esModule = true;
And then exported things either as exports.[varName] or exports.default. They also imported other modules using the const defaultExample = require("./examples/default").default; syntax (or const something = require("./examples/whatever").something;). As in
const defaultExample = require("./examples/default").default;
"use strict";
exports.__esModule = true;
exports.someArray = ["one", "two", "three"];
exports.defaultExample = defaultExample;
The accompanying .d.ts file then looked like this:
export declare interface ExampleInterface {
// ...
}
export declare const defaultExample: ExampleInterface;
export declare const someArray: string[];
// etc
This format of export works correctly in the consuming app. Variables (eg defaultExample) are available, and types are introspected on hover etc. They work smoothly with the specs as well. Weird hacky solution, as generally a library of some sort will do the official compilation, but at least I find it helpful to know how TS modules are simply structured for functional import.

Find all references in VS Code not working across whole project

I have a JavaScript project opened in VS Code. There is nothing fancy there, all *.jsx? are in src folder, files bundled by webpack are stored in dist, there are couple of dependencies described in package.json and installed in node_modules.
Let's say I have two files somewhere in src folder: A.jsx with React component A and B.jsx with React component B which is using component A. When I open my project in VS Code, go to A.jsx and ask code to Find All References of A it's showing only one reference in file A.jsx (with PropTypes declaration). For VS Code to be able to show reference in B.jsx I need to open B.jsx, then go back to A.jsx and only then both references will be shown...
The same scenario works correctly when files are named A.js and B.js, the problem seems to be with *.jsx extenstion.
What I'd like to have is a way to find all references in whole project without a need to open all files no matter if the file is save as .jsx or .js. Is there a way to achieve this?
I've already tried jsconfig.json with
{
"include": ["src/**/*", "src/**/*.jsx"]
}
and
"files.associations": {
"*.jsx": "javascriptreact"
},
in my settings.json
Ok, I finally googled the solution. In order to load .jsx files into the project, VS Code needs jsconfig.json with such content:
{
"compilerOptions": {
"jsx": "react"
}
}
Here is the answer in their repo: https://github.com/microsoft/vscode/issues/100251#issuecomment-646239840

Files generated by TypeScript compiler not recognized as project files in PhpStorm

I use PhpStorm 2017.2.3. I don't know if it's an IDE bug, or if I'm doing something wrong but the .js files generated by TypeScript compiler are somehow "invisible" as far as the project is concerned.
I have created a separate project to demonstrate this issue in isolation. It contains only 4 files: one JavaScript file added manually (manually-added.js), one JavaScript file generated by TypeScript compiler (typescript-generated.js), a TypeScript file (typescript-generated.ts) and a tsconfig.json file with the following configuration:
{
"compilerOptions": {
"target": "es5",
"moduleResolution": "node",
"module": "commonjs"
}
}
The only thing I have done apart from creating these files was checking Enable TypeScript Comipler in PhpStorm Settings and pointing it to my tsconfig.json file.
And here's how it looks in PhpStorm:
Note the different icon of typescript-generated.js file. It suggests that something is wrong with this file (and this is indeed the case). Here's what:
It has a different icon as mentioned above.
You can't use Mark as Plain Text on it (if you do nothing happens).
It is "invisible" to file watchers and scopes.
As you can see scopes and file watchers detect only 3 files instead of 4:
All suggestions will be appreciated.

Is my jsconfig.json not working in Visual Studio Code?

I have added a jsconfig.json in the root of my javascript project to try and exclude some build files as well as set some path mappings but nothing seems to happen. Part of the problem is that I'm not sure what the expected outcome is when using a jsconfig.json, I've read the documentation for it but it does not demonstrate any of the results.
Can someone provide me with a small and working jsconfig.json with a description of what it actually does? So that I can use it to verify that it actually works in my project as well.
Or, does someone know of a way to verify that a jsconfig.json is working/picked up by VS Code?
In my project i was using jsconfig.json file for accesss the file imports directly from the ./src directory from wherever i am trying to import.
My jsconfig.json looks like:
{
"compilerOptions": {
"baseUrl": "./src"
},
"include": [
"src"
]
}
include:
If no include attribute is present, then this defaults to including all files in the containing directory and subdirectories. When a include attribute is specified, only those files are included
baseUrl:
This gives the base directory for the file import path
this is my project structure where i have used jsconfig.json
so if i need to import a function from src/util/auth_util.js inside src/component/Login/index.js
inside src/component/Login/index.js
src/component/Login/index.js :
import { userLogin } from 'util/auth_util.js'
import statement if jsconfig.json as mentioned above not used
src/component/Login/index.js :
import { userLogin } from '../../util/auth_util.js'

Do I have to reference TypeScript definition in every file?

Is there a way to tell TypeScript to use a certain file (or set of files) as a definition for everything compiled?
My only alternative currently is to add something like this in every single TypeScript file (which seems clunky):
/// <reference path="DefinitelyTyped/requirejs/require.d.ts" />
When using TypeScript's internal module system, you can avoid having any <reference> tags at all in the code. I personally do this because I don't want to encode paths (realtive or absolute) within the code as I constantly move stuff around.
One way to do this is by making sure all required declaration files and TypeScript source files are passed to the compiler as arguments during compile time.
Using gulp together with gulp-typescript simplifies this task. You can set noExternalResolve in gulp-typescript to true, and create gulp tasks that take all your .d.ts files along with your sources and pipe it down to the compiler. When you pull in tsd into your stack, you only need to pass the tsd.d.tsfile that contains references to all other definition files installed via tsd.
UPDATE for TypeScript >= v1.5: you can use a tsconfig.json file, and the compiler will get the ordering of the classes right. This removes the need to use gulp-typescript alltogether. You can either chose to have all files explicitly listed in the tsconfig.json file, or completely leave out the files property to include all *.ts/*.tsx files within the directory the tsconfig.json resides (including all subfolders).
A sample tsconfig.jsonmay look like:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"lib": [ "es5", "es2015.promise", "dom" ]
},
"include": [
"src/**/*.ts"
]
}
What I've learned so far is that /// < reference >-ing a module with reference comments is not a good method.
For example: in case you have a file Foo and a file Bar. Both files use jquery, but only file Foo has a reference comment to jquery. If file Foo is deleted for some reason, your file Bar is broken, because the reference is missing.
If you are using TypeScript >= 2.0 It is better to define the TypeScript definition files (.d.ts) in your tsconfig.json under the "files" section.
This could look like this:
{
"compileOnSave": true,
"compilerOptions": {
"noImplicitAny": true,
"noEmitOnError": true,
"removeComments": false,
"sourceMap": true,
"target": "es5",
"outDir": "./Scripts/"
},
"files": [
"./src/foo.ts",
"./src/bar.ts",
"./Scripts/typings/jquery/jquery.d.ts",
"./Scripts/typings/jqueryui/jqueryui.d.ts",
"./Scripts/MicrosoftMaps/Microsoft.Maps.d.ts"
]
}
Using the /// directive (reference comments) is often used in examples to get you started quickly, but it is not a best practice. Also many examples come from a version < TypeScript 2.0.
Some IDEs auto-detect all the files in a project (Visual Studio).
For everything else, you can create a _references.ts file and put all of your reference comments in there - then you only ever need to add:
/// <reference path="_references.ts" />
...to each file (instead of possibly many).
Your IDE may also support tsconfig files.
This question is a duplicate of Reference typescript definitions in one file, instead of all JS files?
The answer is, for now, add each file you want to reference to your tsconfig.json file's "files" section. It's still many lines, but all in one file.
In future when Typescript 2 is released you can then use the "filesGlob" section and solve the problem in two lines.
I've started recently with TypeScript and as I've understood the internal modules resolution is that yes, you can compile all .ts files from the tsconfig.json's directory and all its subdirectories, provided that you don't have set .ts files in it without /// <references path="" />.
But the order in which the .ts files are compiled into resulting .js files is not determined by the dependencies the files (or classes they contain) have. So it is possible to have a situation where the child class is compiled before the parent one (child inherits from parent relation). Then the code won't run, even though it is compiled successfully. It will complain that it couldn't understand the parent class within the child class. Therefore you need to add a /// <references path="" /> as a hint to the compiler to resolve the dependencies between .ts files.
This is want the Typescript documentation says:
The /// directive is the most common of this group. It serves as a declaration of dependency between files.
Triple-slash references instruct the compiler to include additional files in the compilation process.
They also serve as a method to order the output when using --out or --outFile. Files are emitted to the output file location in the same order as the input after preprocessing pass.

Categories

Resources