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"
CodePudding user response:
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