After finding inspiration in the detailed explanation provided in Typescript Docs on Distributive Conditional Types, I successfully adapted and implemented the concept:
https://i.sstatic.net/P96oO.png
The following code snippet showcases my adaptation, which effectively accomplishes the intended functionality:
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>
https://i.sstatic.net/NF0Tf.png
Explore this concept in Typescript playground
If there are alternative methods or more straightforward approaches to achieving the same outcome, I am eager to learn and explore them further. The current implementation might seem like a workaround, as it lacks clarity in explaining its purpose.
UPDATE (INSIGHT INTO THE PROCESS)
Upon deeper examination to comprehend the underlying functionality of the code, I have managed to break it down into two distinct steps:
STEP 1
Initially, a new object/type is constructed based on the keys from the generic type T
(SOME_OBJECT
in this instance).
For each property key K
, the corresponding value is evaluated to determine if it extends the type string
. If so, the key name is retained as the value; otherwise, it is set to never
. The result can be seen in STEP_1_RESULT
.
https://i.sstatic.net/gk7jr.png
STEP 2
In this phase, we utilize the object generated from step 1 to retrieve all possible values by defining
type STEP_2<T> = T[keyof T]
.
Since keyof T
represents the union of all properties within T
, Typescript returns a union containing all potential values for the STEP_1_RESULT
object when called with members of the keyof T
union.
Ultimately, redundant never
types are eliminated from the union, leaving us with
"title" | "label"
, as demonstrated in our example.
https://i.sstatic.net/Dj0II.png