在TypeScript中,如何获取值属于给定类型的对象类型的键? [英] In TypeScript, how to get the keys of an object type whose values are of a given type?
问题描述
我一直在尝试创建一个由 T
类型的键组成的类型,其值是字符串.在伪代码中,它将是T的 keyof,其中T [P]是字符串
.
I've been trying to create a type that consists of the keys of type T
whose values are strings. In pseudocode it would be keyof T where T[P] is a string
.
我想到的唯一方法是分两个步骤:
The only way I can think of doing this is in two steps:
// a mapped type that filters out properties that aren't strings via a conditional type
type StringValueKeys<T> = { [P in keyof T]: T[P] extends string ? T[P] : never };
// all keys of the above type
type Key<T> = keyof StringValueKeys<T>;
但是TS编译器说 Key< T>
仅等于T的 keyof
,即使我已经滤除了值不是字符串的键通过使用条件类型将它们设置为从不
.
However the TS compiler is saying that Key<T>
is simply equal to keyof T
, even though I've filtered out the keys whose values aren't strings by setting them to never
using a conditional type.
因此它仍然允许这样做,例如:
So it is still allowing this, for example:
interface Thing {
id: string;
price: number;
other: { stuff: boolean };
}
const key: Key<Thing> = 'other';
当 key
的唯一允许值实际上应该是"id"
而不是"id"时|价格" |"other"
,因为其他两个键的值不是字符串.
when the only allowed value of key
should really be "id"
, not "id" | "price" | "other"
, as the other two keys' values are not strings.
推荐答案
这可以通过查找类型,如下所示: This can be done with conditional types and lookup types, like this: 然后拔出其属性与 and then you pull out the keys whose properties match 详细信息: 请注意您在做什么:
Note that what you were doing: 实际上只是将非字符串属性值转换为 was really just turning non-string property values into 希望有帮助.祝你好运! Hope that helps. Good luck! 这篇关于在TypeScript中,如何获取值属于给定类型的对象类型的键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!type KeysMatching<T, V> = {[K in keyof T]-?: T[K] extends V ? K : never}[keyof T];
string
匹配的键,如下所示:string
like this:const key: KeysMatching<Thing, string> = 'other'; // ERROR!
// '"other"' is not assignable to type '"id"'
KeysMatching<Thing, string> ➡
{[K in keyof Thing]-?: Thing[K] extends string ? K : never}[keyof Thing] ➡
{
id: string extends string ? 'id' : never;
price: number extends string ? 'number' : never;
other: { stuff: boolean } extends string ? 'other' : never;
}['id'|'price'|'other'] ➡
{ id: 'id', price: never, other: never }['id' | 'price' | 'other'] ➡
'id' | never | never ➡
'id'
type SetNonStringToNever<T> = { [P in keyof T]: T[P] extends string ? T[P] : never };
从不
属性值.它没有碰按键.您的事物
将变为 {id:字符串,价格:从不,其他:从不}
.并且其键与 Thing
的键相同.与 KeysMatching
的主要区别在于,您应该选择键,而不是值(因此,选择 P
而不是 T [P]
).never
property values. It wasn't touching the keys. Your Thing
would become {id: string, price: never, other: never}
. And the keys of that are the same as the keys of Thing
. The main difference with that and KeysMatching
is that you should be selecting keys, not values (so P
and not T[P]
).