0

I'm trying to write a function getDocument which would do the following:

interface DocumentReference<T> {
  get(): Promise<T>;
}

interface ParentA {
  foo: DocumentReference<User>;
}

interface ParentB {
  bar: DocumentReference<Company>;
}

// getDocument<ParentType>(parent: ParentType, fieldName: keyof ParentType): Promise<???>
getDocument(parentA, 'foo') // return a Promise<User>
getDocument(parentB, 'bar') // return a Promise<Company>

I've been trying many different combinations of generic signatures for getDocument but can't figure out how to restrict fieldName so that it corresponds to a field value of type DocumentReference. I don't know how to extract the generic parameter of DocumentReference<T> into the return type either.

Is this doable in typescript? If yes, any pointers?

ldiqual
  • 15,015
  • 6
  • 52
  • 90

1 Answers1

0
interface User {
    a: number
}
interface Company {
    b: string
}
interface DocumentReference<T> {
    get(): Promise<T>;
}

interface ParentA {
    foo: DocumentReference<User>;
}

interface ParentB {
    bar: DocumentReference<Company>;
}

declare function getDocument<T extends ParentA | ParentB, K extends keyof T>(value: T, key: K): Promise<T[K] extends DocumentReference<infer R> ? R : never>;
declare const parentA: ParentA
declare const parentB: ParentB
getDocument(parentA,'foo')
getDocument(parentB,'bar')
Asurance
  • 57
  • 7