Skip to content

Instantly share code, notes, and snippets.

@fvilante
Last active July 31, 2019 21:06
Show Gist options
  • Save fvilante/60db584c117a4371ef1369a65ce6004d to your computer and use it in GitHub Desktop.
Save fvilante/60db584c117a4371ef1369a65ce6004d to your computer and use it in GitHub Desktop.
Utility type to introspect an interface
// Author: Flavio
type __PairList<T> = {
[Key in keyof T]: {
readonly key: Key
readonly value: T[Key]
}
}
type __Pair<T> = __PairList<T>[keyof T]
type AnyPair = __Pair<any>
// --------------------------
// utils - interface Parser
// --------------------------
type TKey = string | number | symbol
/** Final operations over a Pair */
type __GetKeys<T extends {readonly key: any}> = T['key']
type __GetValue<T extends {readonly value: any}> = T['value']
/** Result is a Pair */
type __FilterKeysByValue<T, Value extends T[keyof T]> = Extract<__Pair<T>, {readonly value: Value}>
type GetKeys<T> = __GetKeys<__Pair<T>>
type GetValues<T> = __GetValue<__Pair<T>>
type FilterKeysByValue<T, Value extends T[keyof T]> = __GetKeys<__FilterKeysByValue<T, Value>>
// ========================================
// informal test
// ========================================
const Test01 = {
// space
'milimeter': 'Space',
'meter': 'Space',
// time
'second': 'Time',
'minute': 'Time',
} as const
type Test01 = typeof Test01
// put cursor over types bellow to see type inference result (use vscode with Typescript Plugin)
type Get_Keys = GetKeys<Test01> // OK "milimeter" | "meter" | "second" | "minute"
type Get_Values = GetValues<Test01> // OK "Space" | "Time"
type Get_Only_Space = FilterKeysByValue<Test01,'Space'> // OK "milimeter" | "meter"
// ---------
// Test 02
// ---------
const Test02 = {
// space
'milimeter': {name: 'Oi', number: 10},
'meter': 'Space',
// time
'second': 'Time',
'minute': {name: 'Oi', number: 20},
} as const
type Test02 = typeof Test02
type _PairList = __PairList<Test02> // OK
type _Get_Keys = GetKeys<Test02> // OK "milimeter" | "meter" | "second" | "minute"
type _Get_Values = GetValues<Test02> // OK
type _Get_Only_Space = FilterKeysByValue<Test02, {
readonly name: "Oi";
readonly number: 10;
}> // // OK "milimeter"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment