最简单的例子
假设这种类型
type Foo = { a: number } | { b: string } | { c: boolean };
是否可以得到
type KeysOfFoo = 'a' | 'b' | 'c';
我试过了,但没用
type Failed = keyof Foo; // never
最佳答案
类似于 keyof (A | B | C)
将仅生成 A | B | C
类型的对象上肯定的键,这意味着它必须是 A
的全部中已知的 key 。 , B
,和C
,即:keyof A & keyof B & keyof C
。即keyof T
是“contravariant 在 T
”。
但这不是您想要的(在您的情况下,没有共同的键,因此交集为 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
一起。我只是说要小心。
关于typescript - 是否可以从对象的联合中获取 key ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61685168/