I want to extract the string
properties from SOME_OBJECT
and get it as a union type. Therefore, in the example below, I expect STRING_KEYS
to be of type "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"
This is what I'm getting:
I think I'm in the right direction here (by using conditional types), but I'm not quiet there yet. What is the best way to achieve this?
Got the idea from the example below from Typescript Docs: Distributive Conditional Types
So I've adapted it, and it works:
Typescript playground
If possible, I'm still interested in see other ways of doing that. Especially if there are more straightforward ways of doing it, as I think this answer feels like a "hack", 'cause it does not make it very clear what the code is doing.
UPDATE (HOW IT WORKS)
I've studied a bit more to understand what the code is actually doing, and I think I've figured it out.
I've broken it into two steps:
STEP 1
In the first step, a new object/type will be created.
The keys for this new object will the same keys
K in keyof T
as from the keys of the generic typeT
(SOME_OBJECT
in the example).And for the values of those keys, we'll check in the generic type
T
, if the values for those propertiesK
extendsstring
. Which means that those values are assignable tostring
. For example:string
,"some_hard_coded_string_type"
andany
will all pass the test.For each property that passes the test, we will repeat its key
K
name as the value for them, otherwise will passnever
. You can see the result inSTEP_1_RESULT
below.STEP 2
In this step, we'll simply get that object generated from the step 1, and ask Typescript to return all of its possible values, by doing
type STEP_2<T> = T[keyof T]
.Remember that
keyof T
represents the union of all properties fromT
. So Typescript will return a union with all possible values for theSTEP_1_RESULT
object when called with the members of thekeyof T
union.In our example, it will return
"title" | "label" | never | never | never
.But since the
never
types are meaningless inside a union type, those values are discarded and we are left with"title" | "label"
.