如何从 Typescript 的接口中提取 "string" 属性 名称?
How to extract "string" property names from an interface in Typescript?
我想从 SOME_OBJECT
中提取 string
属性并将其作为联合类型获取。因此,在下面的示例中,我希望 STRING_KEYS
的类型为 "title" | "label"
interface SOME_OBJECT {
title: string,
label: string,
someBool: boolean,
someDate: Date,
someNumber: number
}
type ExtractString<T> = keyof T extends string ? keyof T : never;
type STRING_KEYS = ExtractString<SOME_OBJECT> // <----- THIS SHOULD BE "title" | "label"
这是我得到的:
我认为我的方向是正确的(通过使用条件类型),但我还没有安静下来。实现此目标的最佳方法是什么?
我不太确定条件类型。我可能会在这里尝试使用的是 Pick 并且我会做类似
的事情
interface SOME_OBJECT {
title: string,
label: string,
someBool: boolean,
someDate: Date,
someNumber: number
}
type ExtractString = Pick<SOME_OBJECT, "title" | "label">;
type STRING_KEYS = ExtractString
从 Typescript Docs: Distributive Conditional Types
下面的例子中得到了灵感
所以我对其进行了调整,并且有效:
interface SOME_OBJECT {
title: string,
label: string,
someBool: boolean,
someDate: Date,
someNumber: number
}
type ExtractStringPropertyNames<T> = {
[K in keyof T]: T[K] extends string ? K : never
}[keyof T]
type STRING_KEYS = ExtractStringPropertyNames<SOME_OBJECT>
如果可能的话,我仍然有兴趣了解其他方法。特别是如果有更直接的方法来做到这一点,因为我认为这个答案感觉像是一个“hack”,因为它并不能很清楚地说明代码在做什么。
更新(如何运作)
我研究了更多以了解代码的实际作用,我想我已经弄明白了。
我将其分为两步:
第 1 步
第一步,将创建一个新的object/type。
此新对象的键将与通用类型 T
(示例中的 SOME_OBJECT
)的键相同 K in keyof T
。
对于这些键的值,如果这些属性的值 K
扩展 string
,我们将检查泛型类型 T
。这意味着这些值可以分配给 string
。例如:string
、"some_hard_coded_string_type"
和any
都会通过测试。
对于每个通过测试的属性,我们将重复其键K
名称作为它们的值,否则将通过never
。您可以在下面的 STEP_1_RESULT
中看到结果。
第 2 步
在这一步中,我们将简单地获取从 步骤 1 生成的对象,然后询问
通过 type STEP_2<T> = T[keyof T]
.
将其所有可能值打字稿 return
请记住,keyof T
表示 T
中所有属性的并集。因此,当与 keyof T
联合的成员一起调用时,Typescript 将 return 与 STEP_1_RESULT
对象的所有可能值的联合。
在我们的示例中,它将 return "title" | "label" | never | never | never
。
但是由于 never
类型在联合类型中没有意义,这些值被丢弃,我们只剩下 "title" | "label"
。
我想从 SOME_OBJECT
中提取 string
属性并将其作为联合类型获取。因此,在下面的示例中,我希望 STRING_KEYS
的类型为 "title" | "label"
interface SOME_OBJECT {
title: string,
label: string,
someBool: boolean,
someDate: Date,
someNumber: number
}
type ExtractString<T> = keyof T extends string ? keyof T : never;
type STRING_KEYS = ExtractString<SOME_OBJECT> // <----- THIS SHOULD BE "title" | "label"
这是我得到的:
我认为我的方向是正确的(通过使用条件类型),但我还没有安静下来。实现此目标的最佳方法是什么?
我不太确定条件类型。我可能会在这里尝试使用的是 Pick 并且我会做类似
的事情interface SOME_OBJECT {
title: string,
label: string,
someBool: boolean,
someDate: Date,
someNumber: number
}
type ExtractString = Pick<SOME_OBJECT, "title" | "label">;
type STRING_KEYS = ExtractString
从 Typescript Docs: Distributive Conditional Types
下面的例子中得到了灵感所以我对其进行了调整,并且有效:
interface SOME_OBJECT {
title: string,
label: string,
someBool: boolean,
someDate: Date,
someNumber: number
}
type ExtractStringPropertyNames<T> = {
[K in keyof T]: T[K] extends string ? K : never
}[keyof T]
type STRING_KEYS = ExtractStringPropertyNames<SOME_OBJECT>
如果可能的话,我仍然有兴趣了解其他方法。特别是如果有更直接的方法来做到这一点,因为我认为这个答案感觉像是一个“hack”,因为它并不能很清楚地说明代码在做什么。
更新(如何运作)
我研究了更多以了解代码的实际作用,我想我已经弄明白了。
我将其分为两步:
第 1 步
第一步,将创建一个新的object/type。
此新对象的键将与通用类型 T
(示例中的 SOME_OBJECT
)的键相同 K in keyof T
。
对于这些键的值,如果这些属性的值 K
扩展 string
,我们将检查泛型类型 T
。这意味着这些值可以分配给 string
。例如:string
、"some_hard_coded_string_type"
和any
都会通过测试。
对于每个通过测试的属性,我们将重复其键K
名称作为它们的值,否则将通过never
。您可以在下面的 STEP_1_RESULT
中看到结果。
第 2 步
在这一步中,我们将简单地获取从 步骤 1 生成的对象,然后询问
通过 type STEP_2<T> = T[keyof T]
.
请记住,keyof T
表示 T
中所有属性的并集。因此,当与 keyof T
联合的成员一起调用时,Typescript 将 return 与 STEP_1_RESULT
对象的所有可能值的联合。
在我们的示例中,它将 return "title" | "label" | never | never | never
。
但是由于 never
类型在联合类型中没有意义,这些值被丢弃,我们只剩下 "title" | "label"
。