typescript - 是否可以从对象的联合中获取 key ?

标签 typescript typescript3.0

最简单的例子

假设这种类型

type Foo = { a: number } | { b: string } | { c: boolean };

是否可以得到

type KeysOfFoo = 'a' | 'b' | 'c';

我试过了,但没用

type Failed = keyof Foo; // never

TsPlayground

最佳答案

类似于 keyof (A | B | C)将仅生成 A | B | C 类型的对象上肯定的键,这意味着它必须是 A全部中已知的 key 。 , B ,和C ,即:keyof A & keyof B & keyof C 。即keyof T是“contravariantT ”。 但这不是您想要的(在您的情况下,没有共同的键,因此交集为 never )。

如果您要查找联盟成员中至少一个的 key 集,则需要分发 keyof对工会成员的运算符(operator)。幸运的是,有一种方法可以通过distributive conditional types来做到这一点。 。它看起来像这样:

type AllKeys<T> = T extends any ? keyof T : never;

T extends any在类型检查方面没有做太多事情,但它确实向编译器发出信号,表示在 T 上进行操作T 的每个工会成员都应该发生这种情况分开,然后结果将重新组合成一个联合体。这意味着AllKeys<A | B | C>将被视为 AllKeys<A> | AllKeys<B> | AllKeys<C> 。让我们尝试一下:

type KeysOfFoo = AllKeys<Foo>;
// type KeysOfFoo = "a" | "b" | "c"

看起来不错!请注意,实际使用 KeysOfFoo 时应小心与 Foo 类型的对象配合。 keyof是逆变的,原因如下:

function hmm(foo: Foo, k: AllKeys<Foo>) {
  foo[k]; // error!
  // "a" | "b" | "c"' can't be used to index type 'Foo'.
  // Property 'a' does not exist on type 'Foo'
}

索引 foo 不安全与 k出于同样的原因,您无法安全地索引 {a: number} 类型的值与 "b" ...对象上可能不存在 key 。显然你比我更了解你的用例,所以你很可能对AllKeys<Foo>有一些合法的使用。和Foo一起。我只是说要小心。


Playground link to code

关于typescript - 是否可以从对象的联合中获取 key ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61685168/

相关文章:

javascript - 无法运行 typescript 构建任务: 'C:\Program' is not recognized as an internal or external command

typescript - `unknown` 和 `void` 之间的区别

typescript - 尽管使用 es6-promise.d.ts,但找不到名称 'Promise'

tsc - 如何用 typescript 表示嵌套数组

typescript - TypeScript 3.0 中数组的泛型

javascript - 优化大型 TypeScript 文件的编译

javascript - Typescript 3 Angular 7 StopPropagation 和 PreventDefault 不起作用

node.js - 如何在nestjs中手动注入(inject)依赖

typescript :实现联合类型

angular - 删除 Angular Material 文本框边框,不影响其他组件