Problem
给定一个被视为映射的 TypeScript 接口
(将唯一键类型与非唯一值类型相关),可以提取
映射到指定值类型的键类型?
作为一个具体的例子,从WindowEventMap
in lib.dom.d.ts
...
interface WindowEventMap
extends GlobalEventHandlersEventMap, WindowEventHandlersEventMap {
"abort": UIEvent;
"afterprint": Event;
"beforeprint": Event;
"beforeunload": BeforeUnloadEvent;
"blur": FocusEvent;
// ...
}
有一个内置运算符keyof
获取所有密钥:
type FullKeyList = keyof WindowEventMap;
// gives: FullKeyList = "'abort' | 'afterprint' | 'beforeprint' | ..and 93 more"
是否有一些表达式可以仅过滤映射到值类型的键KeyboardEvent
?:
// Goal:
type SubKeyList = SomeExpression<WindowEventMap, KeyboardEvent>;
// would give: SubKeyList = "'keyup' | 'keypress' | 'keydown'"
解决方案尝试
TypeScript 具有条件类型表达式:
T extends U ? X : Y
所以这是一个合理的尝试:
type Filter<K extends keyof M, V, M> = M[K] extends V ? K : never;
它过滤单个类型:
// Passes this test:
type FilteredExample1 = Filter<'keyup', KeyboardEvent, WindowEventMap>;
// gives FilteredExample1 = "'keyup'"
// Passes this test:
type FilteredExample2 = Filter<'blur', KeyboardEvent, WindowEventMap>;
// gives FilteredExample2 = "never"
它可以过滤类型的联合并返回一个新的联合吗?开始看起来不错:
// Passes this test:
type FilteredUnionExample1 = Filter<'keyup' | 'keydown', KeyboardEvent , WindowEventMap>;
// gives FilteredUnionExample1 = "'keyup' | 'keydown'"
但如果联盟的一名或多名成员失败,联盟就会失败:
// Fails this test:
type FilteredUnionExample2 = Filter<'keyup' | 'keydown' | 'blur', KeyboardEvent, WindowEventMap>;
// gives FilteredUnionExample2 = "never" (and not sub-union "'keyup' | 'keydown'")
// And so, it also fails the end-goal usage:
type AllKeysUnion = keyof WindowEventMap;
type FilteredUnionExample3 = Filter<AllKeysUnion, KeyboardEvent , WindowEventMap>;
// gives FilteredUnionExample3 = "never" (not sub-union "'keyup' | 'keypress' | 'keydown'")
这个问题有解决办法吗?