我们说我有这样的界面:
interface SomeInterface {
field1: string;
field2: number;
field3: string;
field4: SomeOtherType;
}
我希望有一种类型可以提取所有键值是特定类型的键:
type ExtractFieldsOfType<Obj extends {}, Type> = // implementation
ExtractFieldsOfType<SomeInterface, string> // "field1" | "field3"
ExtractFieldsOfType<SomeInterface, number> // "field2"
ExtractFieldsOfType<SomeInterface, SomeOtherType> // "field4"
有可能写出这样的东西吗?我正在编写一个按键名操作对象的函数,但它只允许具有特定值的键。因此,通过类型系统来表达它是很好的。
答案 0 :(得分:5)
您可以在TypeScript 2.8中使用条件类型。
我创建了支持类型AllowedFieldsWithType
以实现更清晰的实施。
type AllowedFieldsWithType<Obj, Type> = {
[K in keyof Obj]: Obj[K] extends Type ? K : never
};
type ExtractFieldsOfType<Obj, Type> = AllowedFieldsWithType<Obj, Type>[keyof Obj]
type StringFields = ExtractFieldsOfType<SomeInterface, string> // "field1" | "field3"
type NumberFields = ExtractFieldsOfType<SomeInterface, number> // "field2"
type ObjectFields = ExtractFieldsOfType<SomeInterface, SomeOtherType> // "field4"
第一种类型:
type AllowedFieldsWithType<Obj, Type> = {
[K in keyof Obj]: Obj[K] extends Type ? K : never
};
1)对于object中的每个字段,我们检查它是否扩展了Type,然后我们返回键的名称作为它的类型。如果不是(例如我们搜索string
,但 field2 是number
类型 - 我们返回never
。这是特殊类型,无法分配任何内容。
AllowedFieldsWithType<SomeInterface, String> equals to: {
field1: 'field1';
field2: never;
field3: 'field3';
field4: never;
}
2)然后我们必须过滤掉never
属性,我们可以使用Pick
来完成,但对于这个用例,我们只需要键名。
3)最终我们使用someType[keyof Obj]
来收集给定类型的值,跳过永远不会。
我写了一篇深入解释这个主题的文章:Create a condition-based subset types