如何在Bun中用require引入类并避免TS2749错误?
解决TypeScript中require引入类/变量赋值类无法直接作为类型的问题
问题重现
模块引入场景
foo.ts文件:
export default class Foo { name = 'bar' }
使用require引入的代码:
const Foo = require('./foo').default function logFoo(foo: Foo) { console.log(foo) } logFoo(new Foo)
运行bun test.ts可正常执行,但TypeScript会抛出错误:TS2749: 'Foo' refers to a value, but is being used as a type here. Did you mean 'typeof Foo'?
单文件场景
class Foo { name = 'bar' } const It = Foo function logFoo(foo: It) { console.log(foo) } logFoo(new Foo)
同样触发TS2749错误,但直接用Foo作为类型则正常。
需求约束
- 不能用
import替换require; - 不能用
typeof声明参数类型,要求require引入的类、本地类、import引入的类的函数参数声明方式完全一致。
解决方案
1. 模块引入(require)场景
通过InstanceType结合typeof提取实例类型,同时保留require的赋值逻辑:
// 先定义与变量同名的类型别名,获取类的实例类型 type Foo = InstanceType<typeof require('./foo').default> // 用require赋值变量 const Foo = require('./foo').default function logFoo(foo: Foo) { console.log(foo) } logFoo(new Foo)
这里的type Foo是类的实例类型,和import Foo from './foo'中直接用Foo作为类型的写法完全一致,满足参数声明方式统一的要求。
2. 单文件场景
直接为变量定义同名的类型别名,复用原类的实例类型:
class Foo { name = 'bar' } // 定义类型别名It,指向Foo的实例类型 type It = Foo // 变量It赋值为Foo构造函数 const It = Foo function logFoo(foo: It) { console.log(foo) } logFoo(new Foo)
此时参数foo: It的写法和直接用foo: Foo完全一致,不会触发TS2749错误。
原理说明
TypeScript中,class Foo同时代表两个东西:
- 值:类的构造函数;
- 类型:类的实例类型。
但当你把构造函数赋值给变量(比如const It = Foo或const Foo = require(...))时,变量仅代表构造函数这个值,不自带实例类型。通过定义同名/同标识的类型别名,我们手动把实例类型绑定到变量名上,让它具备和原类名一样的“值+类型”双重身份,从而实现参数声明方式的统一。
内容的提问来源于stack exchange,提问作者Baptiste
相关产品推荐
相关产品推荐

