检索词
- jsdoc导入
- 汇入 *
- 导入命名空间
- jsdoc命名空间
建议
提供import * as Sub from "./sub"
的JSDoc等效项,以便./sub
模块中的类型和接口可以引用为Sub.Type
、Sub.Interface
。
我对实际的语法没有偏好,但根据我的经验,通常期望以下语法能够做到这一点(但事实并非如此,而且我似乎无法理解Sub
在这里会产生什么结果:
@typedef {import('./sub')} Sub
如果以上不是可行的选项,也许使用相同的*
字符可以是一个选项:
@typedef {import('./sub').*} Sub
或者可能是全新的@import
jsdoc标记。
用例
js-ipfs(相当大的代码库)已经通过JSDoc语法采用了TS,但是处理大量从其他模块导入的类型和接口是一个主要的痛苦来源,原因如下:
1.每一种类型都需要@typedef {import('...').Name} Alias
。
1.导入泛型类型/接口需要通过@template
标记重复类型参数
- 这很容易出错,因为如果省略它,它将变成
any
- 最后需要大量打字
- 对库布局的更改需要更新整个代码库中的所有类型定义(很遗憾,vscode在这方面帮不上忙)
- 另一种方法是将它们合并到一个地方,但是vscode(和类似的)需要多次跳转/单击才能到达实际的类型定义。
以上所有这些都使原本大多是好的经历变成了痛苦。
目前的方法还有一个副作用,就是将导入的接口转换为类型(参见#41258),而这些类型不能在implements
语法中使用,因为它们不再是接口。
假设可以执行import * as Sub from "./sub"
以获得TS语法中的导出的命名空间,则在jsdoc语法中似乎等效于:
1.允许减少@typedef {import(...).Name} Name
声明的数量。
1.允许导入泛型类型,而不必通过@temaplate
标记重新键入类型参数。
1.避免转动接口。
示例
考虑以下TS代码:
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> {
// ...
}
}
使用JSDoc语法的相同代码变为以下代码:
/**
* @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) {
// ...
}
}
注意:由于#41258,上述代码甚至不会生成所需的typedef
现在,如果我们有这个问题的建议,它将是:
/**
* @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) {
// ...
}
}
检查清单
我的建议符合以下准则:
- 这不会是对现有TypeScript/JavaScript代码的重大更改
- 这不会改变现有JavaScript代码的运行时行为
- 这可以在不基于表达式的类型发出不同JS的情况下实现
- 这不是运行时功能(例如,库功能、带有JavaScript输出的非ECMAScript语法等)
- 这个特性将与TypeScript's Design Goals的其余部分一致。
9条答案
按热度按时间toe950271#
cc @sandersn,用于查看能见度
whitzsjs2#
今天遇到了类似的相关问题
我尝试执行以下操作
其中,
types.js
为然后我得到了
'T'仅指涉型别,但在这里是当做命名空间使用。
我想把整个包当作一个命名空间,这样我就可以导入它,并使用
import()
函数语法引用其中的类型,但看起来这只返回类型,而不返回命名空间。m528fe3b3#
@哥扎拉
由于随机愚蠢的运气和只是尝试的东西,我发现你可以在一个项目(www.example.com)
declare ...
https://github.com/voxpelli/types-in-js/blob/main/FAQ.md#i-want-to-share-some-helper-interfaces-or-aliases-globally-in-my-jsdoc-project。您可以声明
@multiformats/codecs/declare.d.ts
中存在各种类型,然后将其包含在jsconfig
/tsconfig
中,以便这些标记在全局范围内可用。您也可以使用命名空间来
namespace codecs { interface BlockEncoder }
这并不能解决任何导入用例,但是事实证明,编写导出的作者可以导出到一个全局名称空间,该名称空间可以在任何地方使用,而无需使用
import
语法。biswetbf4#
可怜的男人的解决方案我已经确定是沿着这些路线:
lib.js(实作位于此处)
result.js(只是lib.js的一个外观)
result.ts(阴影.js以添加类型)
现在,任何其他模块都可以执行以下操作:
gojuced75#
我想澄清一下问题的实质,主要是:
实际上相当于:
但是,在TypeScript中,以下内容通常是不同的:
px9o7tmv6#
嘿,队员们,
我一直在引入外观文件来解决每次导入时重新输入所有泛型的问题,但我确实觉得需要一个合适的解决方案。我还遇到了#22160,它似乎要求使用不同的语法来获得相同的特性。
at0kjp5o7#
不确定是否相关,但似乎
@typedef
并没有真正注册为类型符号这会影响构造函数,使我无法看到构造函数上的签名和自动完成
pftdvrlh8#
@RyanCavanaugh@sandersn对此有什么更新吗?这可能是在使用带有JSDoc的TS时最烦人的限制。
如果有人愿意在这方面指导我,我会把我的时间放在这上面。
vsnjm48y9#
编辑:这似乎不是我在前面的评论中所说的情况
我的问题实际上是
@typedef
没有按预期工作使用
@type
是我所期望的但是
@typedef
没有使用
@var
也不是解决方案