简体   繁体   中英

Typescript Interface, reference one instance property for dynamic second property

I want to use a property within a Typescript Interface's instance to compute a second property. I've been looking into Generics but I'm not successfully implementing this yet. :

Here's an example

// Here I define all valid names - works fine!

type ModalNames = 'payment' | 'source'

// This interface implements all expected payloads
//  for each name 

interface ModalPayloads {
  payment: {
    plan: string
  }
  source: {
    metadataId: string
  }
}


// How do I use the instance name
//  to grab the correct payload property?
export interface ShowModalPayload {
  name: ModalNames
  modalProps?: ModalPayloads[instance.name]
}

In other words, for a given instance of ShowModalPayload , I want to assign modalProps to a type derived from instance.name . Hopefully this makes sense!

I'd use generics for this:

export interface ShowModalPayload<K extends ModalNames> {
  name: K
  modalProps?: ModalPayloads[K]
}

Note the use of ModalPayloads[K] in place of ModalPayloads[instance.name] . That's called a lookup type and it allows you to describe the type of m[k] where m has type ModalPayloads and k has type K .

Anyway the ShowModalPayload interface is now generic in K , which should be one of the ModalNames literals:

declare const smpPayment: ShowModalPayload<'payment'>;
smpPayment.name // "payment"
smpPayment.modalProps // {plan: string} | undefined

declare const smpSource: ShowModalPayload<'source'>;
smpSource.name // "source"
smpSource.modalProps // {metadataId: string} | undefined

Those correspond to what you're looking for, I think. Note that the following is still possible:

declare const smpWhoKnows: ShowModalPayload<ModalNames>
smpWhoKnows.name // ModalNames
smpWhoKnows.modalProps // {plan: string} | {metadataId: string} | undefined

which is possibly not what you want, but is not prohibited. The above definition is probably sufficient for most use cases, though.

Hope that helps. Good luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM