JSDoc equivalent of import *
See original GitHub issueSearch Terms
- jsdoc import
- import *
- import namespace
- jsdoc namespace
Suggestion
Provide a JSDoc equivalent of import * as Sub from "./sub"
so that types & interfaces from the ./sub
module could be referenced as Sub.Type
, Sub.Interface
.
I have no preference in terms of actual syntax, but in my experience general expectation had been that following syntax should do just that (but it is not and I can’t seem to figure out what does Sub
results in here:
@typedef {import('./sub')} Sub
If above is not a viable options maybe using same *
character could be an options:
@typedef {import('./sub').*} Sub
Or maybe whole new @import
jsdoc tag.
Use Cases
js-ipfs (fairly large code base) has adopted TS via JSDoc syntax but dealing with large number of imported types & interfaces from other modules had been a major source of pain for following reasons:
- Every single type requires
@typedef {import('...').Name} Alias
. - Importing generic types / interfaces requires repeating type parameters via
@template
tags
- Which is error prone because when omitted it turns into
any
- Ends up require lot of typing
- Changes to library layout requires updating all those typdefs all over the code base (and vscode can’t help there sadly)
- Alternative is to consolidating them in one place, but then vscode (and alike) takes multiple hops / clicks to get you to actual type definition.
All of the above make otherwise mostly good experience to be painful.
Current approach also has side effect of turning imported interfaces into types (see #41258) which than can’t be used in implements
syntax as they are no longer interfaces.
Given that it is possible to do import * as Sub from "./sub"
to get a namespace of exports in TS syntax it seems like equivalent in jsdoc syntax would:
- Allow reduced number of
@typedef {import(...).Name} Name
declarations. - Allow importing generic types without having to retype type parameters via
@temaplate
tags. - Avoid turning interfaces.
Examples
Consider following TS code:
import { BlockEncoder, BlockDecoder } from "@multiformats/codecs"
import { DagNode } form "./node"
class DagPB implements BlockEncoder<0x70, DagNode>, BlockDecoder<0x70, DagNode> {
async encode(node:DagNode):Promise<Uint8Array> {
// ...
}
async decode(bytes:Uint8Array):Promise<DagNode> {
// ...
}
}
Same code with JSDoc syntax turns into following:
/**
* @template {number} Code
* @template T
* @typedef {import('@multiformats/codecs').BlockEncoder<Code, T>} BlockEncoder
*/
/**
* @template {number} Code
* @template T
* @typedef {import('@multiformats/codecs').BlockDecoder<Code, T>} BlockDecoder
*/
/**
* @typedef {import("./node").DagNode} DagNode
*/
/**
* @implements {BlockEncoder<0x70, DagNode>}
* @implements {BlockDecoder<0x70, DagNode>}
*/
class DagPB {
/**
* @param {DagNode} node
* @returns {Promise<Uint8Array>}
*/
async encode(node) {
// ...
}
/**
* @param {Uint8Array} bytes
* @returns {Promise<DagNode>}
*/
async decode(bytes) {
// ...
}
}
Note: Above code won’t even produce desired typedefs due to #41258
And now if we had what this issue proposes it would be:
/**
* @typedef {import('@multiformats/codecs')} Codec
* @typedef {import('./node').DagNode} DagNode
*/
/**
* @implements {Codec.BlockEncoder<0x70, DagNode>}
* @implements {Codec.BlockDecoder<0x70, DagNode>}
*/
class DagPB {
/**
* @param {DagNode} node
* @returns {Promise<Uint8Array>}
*/
async encode(node) {
// ...
}
/**
* @param {Uint8Array} bytes
* @returns {Promise<DagNode>}
*/
async decode(bytes) {
// ...
}
}
Checklist
My suggestion meets these guidelines:
- This wouldn’t be a breaking change in existing TypeScript/JavaScript code
- This wouldn’t change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn’t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
- This feature would agree with the rest of TypeScript’s Design Goals.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:16
- Comments:9 (1 by maintainers)
Top GitHub Comments
Just to clarify what the issue actually is, essentially this:
is actually equivalent to this:
In TypeScript however the following are distinct in general:
@RyanCavanaugh @sandersn any updates on this ? This is probably the most annoying limitation when using TS with JSDoc.
If someone is willing to mentor me on this, I’d be up to put my time into this.