如何从带类型约束的泛型函数正确推断RxJS Subject<T>的泛型T
问题原因
你遇到的编译报错核心是 TypeScript 无法将泛型参数 T 与 Map 存储的联合类型 Subjects<EventTypes> 建立关联:你定义的 collection 存储的是所有事件 Subject 的联合类型,编译器没法确认你当前传入的 name:T 对应的 Subject 刚好就是 Subject<Events<T>> 类型,因此会出现类型不匹配的报错。
解决方案
你可以通过类型断言告诉编译器你已经确认类型匹配,就能解决编译问题,且不会破坏最终调用时的回调参数自动推断能力。
修复后的完整代码如下:
import { Subject, Subscription } from "rxjs"; import type { Observer } from "rxjs"; const EventNames = { a: "a", b: "b", c: "c", } as const; type Payloads = { [EventNames.a]: string; [EventNames.b]: number; [EventNames.c]: boolean; }; type EventTypes = keyof typeof EventNames; // 所有支持的事件对象类型 type Events<T extends EventTypes> = {type: T, payload: Payloads[T]}; // 所有支持的回调类型 type Callback<T extends EventTypes> = (event: Events<T>) => void; // 所有支持的Subject类型 type Subjects<T extends EventTypes> = Subject<Events<T>>; const collection = new Map<EventTypes, Subjects<EventTypes>>(); function fnWithConstraint<T extends EventTypes>( name: T, cb: Callback<T> ): Subscription | null { let subject = collection.get(name) as Subjects<T> | undefined; if (!subject) { subject = new Subject<Events<T>>(); collection.set(name, subject as Subjects<EventTypes>); } const subscription = subject.subscribe(cb); return subscription; } // 调用时会自动推断event类型为 { type: "b", payload: number } fnWithConstraint("b", (event) => console.log(event));
改动说明
- 简化了条件类型的写法,因为泛型T本身已经约束为
EventTypes,不需要额外写T extends EventTypes ? ... : never的判断 - 对从Map中取出的
subject做了明确的Subjects<T>类型断言,告诉编译器这个subject的类型和当前传入的name是匹配的 - 存入Map时也做了
Subjects<EventTypes>的类型断言,因为Map本身就允许存储所有事件类型的Subject,这个断言是完全安全的
内容的提问来源于stack exchange,提问作者Jaz Lalli
相关产品推荐
相关产品推荐

