Home > other >  Extend on a typescript interface and change one value in the extended object
Extend on a typescript interface and change one value in the extended object

Time:10-18

Curious what approach I could use to implement the following simple ts interface extend. I don't want to get rid of the data: {} object since the data axios responds with is inside the response 'data' object.

Supertype

export interface IAxiosResponse {
  data: {
    type: IAlertStatus;
    message: string;
    data?: any;
  };
}

Subtype

export interface YTQueryResponse extends IAxiosResponse {
  data: {
    // how can I get 'type' and 'message' here without hardcoding supertypes type & message?
    data: IYoutubeResponse;
  } 
}

I pretty much just want to set up a pattern to replace only data.data while leaving the other properties alone (their inherited shape is fine). I've tried to implement a few different ts utilities to this end but so far I've been unsuccessful.

for instance, the following doesn't work because it's still looking for data.type and data.message.

export interface YTQueryResponse extends Omit<IAxiosResponse, "data.data"> {
  data: {
    data: IYoutubeResponse;
  };
}

Any thoughts?

CodePudding user response:

by defining your own data interface then passing it to the generic of the builtin AxiosResponse, this is probably the easiest and most useful for most cases.

interface MyDataFormat<T = any> {
    type: IAlertStatus;
    message: string;
    data?: T;
}
export type IAxiosResponse<InnerData = any> = AxiosResponse<MyDataFormat<InnerData>>
// or export interface IAxiosResponse<InnerData = any> extends AxiosResponse<MyDataFormat<InnerData>> {}
export interface YTQueryResponse extends IAxiosResponse< IYoutubeResponse> {}
// or export type YTQueryResponse = IAxiosResponse< IYoutubeResponse>

Or if you do need to extract a field from a bigger type definition (instead of just redefining that type yourself) you can extract the field then write an interface to extend it, although typescript forces you to use some intermediate variable since IAxiosResponse["data"] can't go directly into the extend section of an interface.

type tmp = IAxiosResponse["data"]
interface MyAxiosData<D> extends tmp {
    data: D
}
export interface YTQueryResponse extends IAxiosResponse {
  data: MyAxiosData< IYoutubeResponse>
}

or doing it inline with just a type intersection (which won't complain as clearly if you are intersecting conflicting types but is less overhead for the programmer than above)

export interface YTQueryResponse extends IAxiosResponse {
  data: IAxiosResponse["data"] & {data: IYoutubeResponse};
}
  • Related