-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TypeScript won't import JSDoc types from .js file in node_modules #33136
Comments
UpdateRecently I noticed a situation where TypeScript was able to properly import JSDoc types from an imported module. In the case of my NPM module @composi/core, it has the following file structure:
Of the above, export { h } from './h'
export { render } from './render'
export { run } from './runtime'
export { union } from './union'
export { batchEffects } from './effects'
export { Fragment } from './fragment' When using @composi/core, a project usually imports functions like this: import { h, render, run, union, batchEffects } from '@composi/core' @composi/core's "main": "src/index.js" However, for better tree shaking you could just import the functions you want directly from the other files in the source directory, bypassing the import {h} from '@composi/core/src/h'
import {render} from '@composi/core/src/render' When one does this, all of a sudden TypeScript imports the types correctly for I'm suspecting that the indirection of the |
There's an option in TS |
Now, projects do have a {
"compilerOptions": {
"target": "es6",
"jsx": "react",
"maxNodeModuleJsDepth": 5
},
"include": [
"node_modules/@composi/**/src/*",
]
} |
UpdateI found a hack for countering TypeScripts inability to properly process imported JSDoc types. I imported the file with the types that other files were using into the module's Of course this is a hack that illustrates the problem. A module with an My old export { h } from './h'
export { render } from './render'
export { run } from './runtime'
export { union } from './union'
export { batchEffects } from './effects'
export { Fragment } from './fragment' My new version that forces TypeScript to recognize imported JSDoc types is like this: export { h } from './h'
export { render } from './render'
export { run } from './runtime'
export { union } from './union'
export { batchEffects } from './effects'
export { Fragment } from './fragment'
/**
* The following import is a hack to force TypeScript to properly
* understand JSDoc types defined in the vnode.js file that are used by
* fragment.js, h.js, render.js and vdom.js.
* When TypeScript gets updated to handle this import properly, this will be removed.
*/
import { createVNode } from './vnode' // eslint-disable-line no-unused-vars Note that the |
I'm currently using TypeScript 3.6.3. I'm noticing ellipsis before the imported module name for Why should I need a |
I have found a solution that seem to work well: move // src/index.js
export function delay() {} // index.d.ts
import { delay } from './src'
export { delay } |
I also found another hack to get TypeScript to import JSDoc types that weren't getting imported. Just make so But I'm curious what you're doing with the |
I tried using a export { h } from './h'
export { render } from './render'
export { run } from './runtime'
export { union } from './union'
export { batchEffects } from './effects'
export { Fragment } from './fragment'
/**
* Make types available to programs that use them.
*/
/**
* Type of virutal node used to define elements to create.
* @typedef { import('./vnode').VNode } VNode
*/
/**
* A program which is executed by the `run` function.
* @typedef { import('./runtime').Program } Program
*/
/**
* Message dispatched by the `send` function to the program's `update` method.
* @typedef { import('./runtime').Message } Message
*/
/**
* Type of state, which can be of any type.
* @typedef { import('./runtime').State } State
*/
/**
* Function for sending messages to the program's `update` method.
* @typedef { import('./runtime').Send } Send
*/ This allows the user to import |
For anyone else who has found this issue after it closed, hopefully this helps: Same ProblemI have the same problem as @rbiggs. I've created a module called However, as soon as I'm importing this code to another project, the types disappear. VSCode and Hope?@phaux 's solution (#33136 (comment)) was very helpful to me. I set my tsconfig.json to: {
"compilerOptions": {
"noEmit": true,
"allowJs": true,
"checkJs": true,
"downlevelIteration": true,
"maxNodeModuleJsDepth": 1
},
"include": [...]
} And VSCode and Before: After: Wonderful ✔️ The only problem is that when I ran This is because now every single import is being type checked. Many JavaScript libraries come a-cropper when examined under TypeScript's inscrutable gaze. Fair enough! But I don't have time to fix all these issues with external libraries. ❌ What I want is for TypeScript to just check the modules that I made that I know have been typed properly using JSDoc. How can I do that? The solutionJust add the modules to
This works! ✔️ ✔️ ✔️ Typescript version: 3.6.2 |
Actually, @lukehesluke, that's what I wound up doing as well, using However, now I no longer bother with any of that because TypeScript now supports creating You just need to update your projects {
"compilerOptions": {
"target": "es6",
"allowJs": true,
"checkJs": true,
"moduleResolution": "node",
"alwaysStrict": true,
"strictNullChecks": false,
"emitDeclarationOnly": true,
"declaration": true,
"outDir": "types",
"removeComments": false
}
} Note that I tell TypeScript to output the "typings": "types" With these updates to my JavaScript projects, TypeScript will find the I guess I should mention how I check my types and produce the "scripts": {
"checkjs": "tsc"
} Then in the terminal I just run |
@rbiggs you genius! Thank you, that looks like the ideal solution to this. Am I right in saying that this is primarily these compiler options: "emitDeclarationOnly": true,
"declaration": true, |
Yup. You do need the latest TypeScript installed somewhere, either locally or globally. Latest version is 3.7.5. Set up your |
This issue should be re-opened given that TypeScript does not resolve JS files with JSDoc from node_modules. All proposed solutions in this issue are workarounds. Using the TypeScript compiler to emit declaration files is redundant, given that the JS files contain the declaration already. Moreover, I experienced:
All of those issues would exist if declaration files wouldn't be required for JSDoc JS files. |
I think TypeScript should simply support {
"main": "./main.js",
"types": "./main.js"
} Last time I checked it didn't work. Project which imports such module doesn't get the types. |
Fast forward to 2024 and it still doesn't work and issue is still closed... nothing is fixed here, just hacky and annoying workarounds in sight. |
Please, reopen the issue. Thumbs up this message if you want it to be reopened. Thanks. |
Happy to shared that I have found a way to do similar things and its more friendly due to not need to config In short, you just need to create a facade https://github.com/hyf0/starter-libesm is an example.
Too bad you still need to enable |
TypeScript Version: 3.5.2
I use JSDoc type definitions in my JavaScript and use
checkjs
in VSCode to have TypeScript type check my JavaScript live. This generally works very well. However I have noticed one failure. TypeScript fails to properly understand JSDoc types when they're imported from another file. Let me explain.I have a node module which uses JSDoc to define types. Some of the types are defined in one file and imported into other files using the format:
This type
VNode
gets imported in another file for use as a parameter of a function:In the module itself this works as expected. The type
VNode
is understood everywhere it is used.The problem is when I create a project the uses this module. For some reason TypeScript treats the imported JSDoc type as
any
. I'm currently using VSCode Version: 1.37.1. When i was using 1.36.x I was getting the following warning for the import JSDoc type (sic):What I don't understand is why would TypeScript be looking for a
d.ts
file for a JavaScript file using JSDoc comments for types? Does it know that an import in a JSDoc comment should point to a JSDoc type definition? It seams like when TypeScript sees the@typedef
import statement, it assumes its a normal JavaScript import and starts looking for ad.ts
file. Which leads to it never importing the JSDoc type.Of course I could copy and paste the type definition everywhere I need it. However that leads to maintenance problems when I need to update the type definition.
Since this works inside the module importing JSDoc types from other files, why can't it work when the module is imported into another project?
To show the problem here are some images illustrating a module with a
render
function. In the first image you can see that the importedVNode
type is being imported and interpreted correctly:In the next image you can see that this imported type is being interpreted correctly as a parameter of the
render
function when this is defined:But here, when the
render
function is imported into a project, the imported type is treated by TypeScript asany
:To reproduce this problem do the following.
The above will creaate a new project on your desktop named
Type-Test
.cd
to the new project and run:After the dependencies are installed, open the project in VSCode and go to the
src/js/app.js
file. Hover over the importedrender
function at the top of the page. You'll see Intellisense pop up, but the first argument for VNode will be of typeany
. This is wrong.Now open the project's
node_modules
folder and go tonode_modules/@composi/core/src/render.js
Scroll down to the defintion of therender
funcion. Hover over it or its first parameter. You'll see that here TypeScript is able to correctly understand the imported type asVNode
, not asany
.It seams TypeScript is treated JSDoc import statements as if they were JavaScript imports. It then looks for a
.d.ts
, which doesn't exist because this is JavaScript with JSDoc comments. So it defaults toany
.Interestingly, in earlier versions of VSCode, if I opened the module source code first and hovered over the imported type, this would force VSCode and TypeScript to recognize the type, even in the project where the modules was imported. Currently this no longer works, instead treating such imported JSDoc types as
any
no matter what you do.The text was updated successfully, but these errors were encountered: