如何在项目中正确使用.js与.d.ts文件并解决类型检查问题
问题分析与解决
问题背景
现有some.js文件:
export function myFunc(a, b) { return a.asdf + b; }
尝试通过同目录的some.d.ts为其添加类型声明,期望运行npx tsc时检测到a.asdf的类型错误(asdf is not a member of type number),但实际出现错误:parameter a implicitly has any type。
当前tsconfig.json配置:
{ "compilerOptions": { "allowJs": true, "checkJs": true, "noEmit": true, "strict": true, "skipLibCheck": false }, "include": ["**/*.js", "**/*.d.ts"] }
已尝试的两种声明方式均未生效:
// 方式1 declare namespace some { export function myFunc(a: number, b: number): number; }
// 方式2 declare module "some" { export function myFunc(a: number, b: number): number; }
原因分析
checkJs的行为冲突:开启checkJs后,TypeScript会直接分析JS文件的语法,在strict模式下,未标注类型的参数会触发"implicit any"错误,此时TS不会自动使用同目录的.d.ts声明来覆盖对JS文件的类型推断。- 声明方式错误:
- 直接
export declare function的写法无法关联到同名JS文件的模块; declare namespace some是全局命名空间声明,不适用于ES模块格式的JS文件;declare module "some"是针对npm包的模块声明,而非本地文件的相对模块声明。
- 直接
正确实现方式
要让TypeScript用.d.ts的类型约束来检查JS文件的实现,需按以下步骤操作:
1. 修正.d.ts的模块声明
使用相对路径模块声明,将some.d.ts内容改为:
declare module "./some" { export function myFunc(a: number, b: number): number; }
2. 在JS文件中关联类型声明
在some.js的函数上添加JSDoc注解,明确指定函数的类型来自.d.ts的声明,让TS用声明的类型来检查实现:
/** @type {import('./some').myFunc} */ export function myFunc(a, b) { return a.asdf + b; }
3. 运行检查
保持原有tsconfig配置即可,此时运行npx tsc,就能得到期望的错误:Property 'asdf' does not exist on type 'number'。
通用替代方案(JS项目中独立管理类型声明)
如果上述方式无法满足需求,JS项目中不依赖单个global.d.ts的类型管理通用方式有两种:
JSDoc内联类型注解:直接在JS文件中用JSDoc标注类型,无需单独编写
.d.ts,示例:/** * @param {number} a * @param {number} b * @returns {number} */ export function myFunc(a, b) { return a.asdf + b; }这种方式直观,TS会直接基于JSDoc的注解做类型检查,无需额外关联
.d.ts文件。按模块拆分
.d.ts:为每个JS模块编写对应的.d.ts文件,使用相对路径模块声明,并在JS文件中通过import type或JSDoc的import()语法关联类型,确保每个模块的类型声明独立管理,不污染全局空间。
内容的提问来源于stack exchange,提问作者Valentine
相关产品推荐
相关产品推荐

