IoC容器resolve方法返回类型的类型推断实现问询
实现IoC容器resolve方法的返回类型自动推断
要让编辑器自动识别resolve方法的返回类型,核心是利用TypeScript的泛型重载和类型追踪能力,通过在bind过程中记录绑定的类型信息,让resolve能根据传入的参数(抽象类型或字符串别名)自动推断出正确的返回类型。以下是具体实现方案:
核心思路
- 用泛型类型追踪容器内所有绑定的类型映射关系
- 给
bind方法设置重载,分别处理抽象类型(构造函数)和字符串别名的绑定逻辑,同时更新泛型类型 - 给
resolve方法设置重载,根据传入参数的类型(构造函数或字符串别名),从泛型映射中匹配对应的返回类型
完整代码实现
// 定义绑定映射的基础类型,键为字符串或Symbol,值为任意类型 type BindingMap = Record<string | symbol, unknown>; class MyContainer<B extends BindingMap = {}> { // 运行时存储绑定的工厂函数 private bindings: Map<string | symbol, () => unknown> = new Map(); // 重载1:绑定抽象类型(构造函数) bind<T>(abstractType: new () => T, factory: () => T): MyContainer<B & { [K in symbol as typeof abstractType]: T }>; // 重载2:绑定字符串别名 bind<T>(alias: string, factory: () => T): MyContainer<B & { [K in typeof alias]: T }>; // bind方法的具体实现 bind<T>(key: string | (new () => T), factory: () => T): MyContainer<B> { // 用Symbol存储构造函数类型的绑定,避免和字符串别名冲突 const mapKey = typeof key === 'string' ? key : Symbol.for(key.name); this.bindings.set(mapKey, factory); // 类型断言更新容器的泛型类型 return this as unknown as MyContainer<B & { [K in typeof mapKey]: T }>; } // 重载1:resolve抽象类型,返回对应实例类型 resolve<T>(abstractType: new () => T): T; // 重载2:resolve字符串别名,返回绑定的对应类型 resolve<K extends keyof B>(alias: K): B[K]; // resolve方法的具体实现 resolve<T>(key: string | (new () => T)): T | B[keyof B] { const mapKey = typeof key === 'string' ? key : Symbol.for(key.name); const factory = this.bindings.get(mapKey); if (!factory) { throw new Error(`未找到绑定:${typeof key === 'string' ? key : key.name}`); } return factory(); } }
关键细节说明
- 泛型追踪绑定:容器类的泛型
B会在每次调用bind时扩展,记录新绑定的类型信息,确保resolve能获取到准确的类型映射。 - 构造函数的类型处理:用
Symbol.for(key.name)作为构造函数绑定的运行时键,避免和字符串别名冲突;类型层面通过typeof abstractType作为泛型映射的键,关联构造函数和其实例类型。 - 重载的作用:
bind和resolve的重载让TypeScript能根据传入参数的类型,自动匹配对应的逻辑并推断返回类型,编辑器就能实时提示正确的类型信息。
使用示例
// 定义抽象类作为抽象类型 abstract class ILogger { abstract log(message: string): void; } // 实现类 class ConsoleLogger extends ILogger { log(message: string) { console.log(`日志:${message}`); } } // 初始化容器并绑定 const container = new MyContainer() .bind(ILogger, () => new ConsoleLogger()) .bind('systemLogger', () => new ConsoleLogger()); // resolve抽象类型,编辑器会识别返回ILogger类型 const logger1 = container.resolve(ILogger); logger1.log('测试抽象类型绑定'); // resolve字符串别名,编辑器会识别返回ConsoleLogger类型 const logger2 = container.resolve('systemLogger'); logger2.log('测试别名绑定');
内容的提问来源于stack exchange,提问作者Nasa
相关产品推荐
相关产品推荐

