【发布时间】:2019-12-04 11:16:27
【问题描述】:
在搜索有关如何编写类型安全事件发射器的选项时,我偶然发现了这种模式,您首先在接口中定义事件名称及其值,例如:
interface UserEvents {
nameChanged: string;
phoneChanged: number;
}
并且 'on' 方法被定义为接受一个 keyof UserEvents,以及一个回调,其参数是由使用称为查找类型的功能获得的键 - UserEvents[keyof T]:
function on<T extends keyof UserEvents>(e: T, cb: (val: UserEvents[T]) => void) {/**/}
提供类型安全的方法调用:
on('nameChanged', (val) => {}); // callback parameter type inferred to be a string
on('phoneChanged', (val) => {}); // ... inferred as number
我遇到的问题是在“on”方法的主体内部,我无法根据传递的键值缩小传递的回调的类型。由于事件名称及其类型是在同一个接口中定义的,因此如果我检查了键类型,我希望回调范围会缩小,但事实并非如此:
function on<T extends keyof UserEvents>(e: T, cb: (_: UserEvents[T]) => void) {
if (e === 'nameChanged') {
// expecting the cb type to be (string) => void
} else {
// and here to be (number) => void
}
// but regardless of the checks, the cb type
// inside the method body is of type (string & number) => void
}
有没有什么方法可以实现基于事件键的回调的自动类型推断,使用其他 TypeScript 功能,如类型保护、区分联合等,以及这个特定的方法调用签名?
【问题讨论】:
-
我有类似的问题......“虽然实现仍然会抱怨,因为 TypeScript 类型保护只会缩小单个值的类型。也就是说,在 if (a) { } else { } , a 的类型可能会在 then 和 else 子句中被缩小,但是当你检查 a 时 b 的类型不会被缩小,即使 a 和 b 的类型之间存在一些约束。”。检查这个question
标签: typescript