Search code examples
typescripttypescript-genericsdiscriminated-unionmapped-types

Given a discriminant, get type of a property for corresponding member of discriminated union


I have the following discriminated union, where the property id acquires a different type based on the value of the discriminant:

type TableKind = 'administration' | 'data'

type AdministrationTableId = 'Modules' | 'Users' | 'Roles'
type DataTableId = number

type GenericIdentifier<K extends TableKind, ID> = { kind: K, id: ID }

type AdministrationTableIdentifier = GenericIdentifier<'administration', AdministrationTableId>
type DataTableIdentifier = GenericIdentifier<'data', DataTableId>

type TableIdentifier = AdministrationTableIdentifier | DataTableIdentifier

I would like to make a generic type that takes the discriminant and returns the type of id property of the corresponding union member:

type GetTableIdType<K extends TableKind> = ???

type AdminId = GetTableIdType<'administration'> // returns AdministrationTableID
type DataId = GetTableIdType<'data'> // returns DataTableId

Is this possible? How could this be achieved?


Solution

  • Just use Extract

    type TableKind = 'administration' | 'data'
    
    type AdministrationTableId = 'Modules' | 'Users' | 'Roles'
    type DataTableId = number
    
    type GenericIdentifier<K extends TableKind, ID> = { kind: K, id: ID }
    
    type AdministrationTableIdentifier = GenericIdentifier<'administration', AdministrationTableId>
    
    type DataTableIdentifier = GenericIdentifier<'data', DataTableId>
    
    type TableIdentifier = AdministrationTableIdentifier | DataTableIdentifier
    
    
    type GetTableIdType<K extends TableKind> = Extract<TableIdentifier, { kind: K }>['id']
    
    type AdminId = GetTableIdType<'administration'> // returns AdministrationTableID
    type DataId = GetTableIdType<'data'> // returns DataTableId
    

    Playground