Reputation: 1146
Lets say I have an interface Obj
:
interface Obj {
string1: string
string2: string
array1: SomeInterface[]
array2: SomeOtherInterface[]
}
How can one extract the keys of the interface Obj
that extends []
as a discriminated union type?
Desired output given Obj
from above:
// "array1" | "array2"
Upvotes: 5
Views: 3875
Reputation: 1146
I would like to add that this syntax is also possible for the same use case:
type ObtainKeys<T, V> = keyof {
[K in keyof T as T[K] extends V ? K : never]: any
}
Upvotes: 4
Reputation: 33041
You need to use mapped types:
type SomeInterface = { tag: 'SomeInterface' }
type SomeOtherInterface = { tag: 'SomeOtherInterface' }
interface Obj {
string1: string
string2: string
array1: SomeInterface[]
array2: SomeOtherInterface[]
}
type ObtainKeys<Obj, Type> = {
[Prop in keyof Obj]: Obj[Prop] extends Type ? Prop : never
}[keyof Obj]
type GetArrayKeys = ObtainKeys<Obj, Array<any>> // "array1" | "array2"
type GetStringKeys = ObtainKeys<Obj, string> // "string1" | "string2"
ObtainKeys
is a generic util, which expects two arguments. First one is an Object you want to check, second one is a type you want to extract.
This line: [Prop in keyof Obj]: Obj[Prop] extends Type ? Prop : never
iterates over all Obj
keys and checks whether Obj[Prop]
extends desired type. Please keep in mind, that Obj[Prop]
is a value and not a key. So, if Obj[Prop]
meets the requirements - return Prop
, otherwise - never
.
I have used [keyof Obj]
in order to get all values of our iterated type, because desired Prop
is in the value
place and union of any type with never
- returns you same type without never
Upvotes: 8