代码之家  ›  专栏  ›  技术社区  ›  Joon

如何在Typescript中获取值T[K]为可调用函数的“keyoft T”的子集

  •  2
  • Joon  · 技术社区  · 6 年前

    我想过滤 keyof T 基于类型 T[keyof T]

    它应该这样工作:

    type KeyOfType<T, U> = ...
    
    KeyOfType<{a: 1, b: '', c: 0, d: () => 1}, number> === 'a' | 'c'
    
    KeyOfType<{a: 1, b: '', c: 0: d: () => 1}, string> === 'b'
    
    KeyOfType<{a: 1, b: '', c: 0: d: () => 1}, Function> === 'd'
    

    这可能吗?

    1 回复  |  直到 6 年前
        1
  •  4
  •   Titian Cernicova-Dragomir    6 年前

    可以使用条件类型和映射类型执行此操作

    type KeyOfType<T, U> = {[P in keyof T]: T[P] extends U ? P: never}[keyof T]
    

    让我们把事情分解一下。

    我们可以从一个映射类型开始,它具有与原始类型相同的属性 T ,这是一个简单的标准映射类型:

    type KeyOfType<T> = { [P in keyof T]: T[P] } // New Type same as the original
    

    T[P] 是类型查询,表示键的类型 P 输入 T型 . 我们可以把这个改成 第页 ,表示新属性的类型与其名称相同:

    type KeyOfType<T> = { [P in keyof T]: P }
    // So
    KeyOfType<{ a: number, b: string }> == { a: 'a', b: 'b' }
    

    我们可以向该类型添加一个类型查询,以再次获取该类型的所有键一般来说 T[keyof T] 获取类型的所有属性类型。将此应用于我们的映射类型,该映射类型的属性类型与我们基本上返回到的键名称相同 keyof T :

    type KeyOfType<T> = { [P in keyof T]: P }[keyof T]
    // So
    KeyOfType<{ a: number, b: string }> ==  'a'|'b' 
    

    现在我们可以将条件类型添加到o not always select 第页 是的。自从 A | never == A 我们可以将映射类型中的属性类型设置为never if( T[P] )不满足某个约束。

    为了表示约束,我们添加了一个额外的泛型参数 U 我们使用一个条件类型 T extends U ? TypeIfTrue: TYpeIfFalse 是的。把它放在一起我们得到:

    键入keyof type<T,U>={[P in keyoftt]:T[P]扩展UP:never}[keyof T T]