fuafa/not-a-hub

在 JavaScript 的项目里享受 d.ts 类型提示

Opened this issue · 0 comments

fuafa commented

文件结构

project
|- src
   |- index.js
   |- package
     |- module.js
     |- module.d.ts

index.jsimport module

// module.js

export function foo(x) {
  return x;
}
// module.d.ts

export declare function foo(x: number): number;
// index.js

import { foo } from './src/module';

// foo 的类型是 number -> number
// 因为有一个同名的 d.ts 文件,TypeScript 可以找到相对应的类型,
// 但是生成 JS 文件中 `foo` 还是会正确的指向 module.js 中的 `foo`
foo

然而 module.js 并不能享受到 module.d.ts 中的类型提示

// module.js

// foo 的类型是 any -> any
export function foo(x) {
  return x;
}

因为 module.js 和 module.d.ts 是两个不同的 module(指 ES 中的 module), 他们有属于自己的作用域。

让 module.js 也享受 module.d.ts 的类型提示

目前只能通过在 js-doc 中使用动态 import 的语法,把 foo 联系起来。

// module.js

/**
 * 
 * @type {import("./module").foo}
 * 这里 foo 的类型是 number -> number
 */
export function foo(x) { return x; }

如果 module 里有多个方法,那么

/**
 * 
 * @typedef {import("./module")} Module  
 */

/**
 * 
 * @type {Module["foo"]}
 */
export function foo(x) {
    return {}
}

神 TM 展望未来

未来可能会引入新的 js-doc tag named @import and @from, 好处是看起比上面的 intuitive.

有两种 proposals:

  1. 难看,跟 ESModule syntax 不一样,但是有更强大的自动补全
/**
 * 
 * @from "./module"
 * @import { foo } from
 * @import Default
 * @import * as ns 
 */
  1. 补全没有 1 好,但是语法跟 ESModule syntax 一样
/**
 * @import { foo, y as z, default as Default } from "./module"
 */

Conclusion

这么麻烦,还不如直接写 TypeScript...

Reference:

microsoft/TypeScript#14342
microsoft/TypeScript#14377
microsoft/TypeScript#14844
microsoft/TypeScript#22160