在 TypeScript 中,如何获取值属于给定类型的对象类型的键? [英] In TypeScript, how to get the keys of an object type whose values are of a given type?

查看:70
本文介绍了在 TypeScript 中,如何获取值属于给定类型的对象类型的键?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试创建一个类型,该类型由 T 类型的键组成,其值为字符串.在伪代码中,它是 keyof T 其中 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 只是等于 keyof T,即使我已经过滤掉了那些值不是字符串的键通过使用条件类型将它们设置为 never.

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.

链接到 TypeScript 操场中的代码示例

推荐答案

这可以通过 条件类型索引访问类型,像这样:

This can be done with conditional types and indexed access types, like this:

type KeysMatching<T, V> = {[K in keyof T]-?: T[K] extends V ? K : never}[keyof T];

然后你像这样拉出属性匹配string的键:

and then you pull out the keys whose properties match 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'


注意你在做什么:


Note that what you were doing:

type SetNonStringToNever<T> = { [P in keyof T]: T[P] extends string ? T[P] : never };

实际上只是将非字符串属性 values 转换为 never 属性值.它没有接触按键.你的 Thing 会变成 {id: string, price: never, other: never}.而那个的键和Thing的键是一样的.与 KeysMatching 的主要区别在于您应该选择键,而不是值(所以 P 而不是 T[P]).

was really just turning non-string property values into 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]).

游乐场连结代码

这篇关于在 TypeScript 中,如何获取值属于给定类型的对象类型的键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆