Reputation: 135
I have a situation of nested types and what I would like to achieve is to have a specified property based on another property's value.
In the HTML I cycle the response of an API and, based on the type value received, I would like to have a different option value.
For example: if I receive a response where type is 'articles' I would like to have OptionArticles as ChatOptions.
Is there a solution for this?
This is the code:
export interface ChatMessage {
status: string;
query: string;
step: string;
richResponse: boolean;
payload: ChatPayload;
sessionId?: number;
}
interface ChatPayload {
type: ChatTypes;
options: ChatOptions;
confidence?: number;
gotAllParams?: boolean;
}
type ChatTypes = 'text' | 'date' | 'articles' | 'params';
type ChatOptions = OptionText | OptionArticles | OptionParams;
interface OptionText {
type: 'text' | 'date';
text: string[];
}
interface OptionArticles {
type: 'articles';
prefilled: Values[];
possible: Values[];
}
interface OptionParams {
type: 'params';
params: FineParams;
}
Thanks.
Upvotes: 3
Views: 3209
Reputation: 3106
You can use conditional types to enforce that the type in chatPayload
is the same as the type in chatPayload.options
.
ChatPayload can take as a type parameter the "type" from the API:
interface ChatPayload<Type extends ChatTypes> {
type: Type;
options: Type extends "articles" ? OptionArticles : Type extends "params" ? OptionParams : OptionText ;
confidence?: number;
gotAllParams?: boolean;
}
And you can switch the type depending on the value of the field in the API response:
// the response you get from the API; you don't know the type yet
const apiResponse: any = {}
if (apiResponse.type === "text" || apiResponse.type === "date") {
doSomething(apiResponse as ChatPayload<"text" | "date">)
} else if (apiResponse.type === "articles") {
doSomething(apiResponse as ChatPayload<"articles">)
} else if (apiResponse.type === "params") {
doSomething(apiResponse as ChatPayload<"params">)
} else {
throw new Error("unexpected type")
}
The casting is a little ugly, but you will have to use a cast in order to get an untyped API response into one of your own types.
For further safety, you can use a JSON validator to make sure that the response you're getting from the API conforms to what you expect.
Upvotes: 2
Reputation: 619
Maybe you can use a setter for a field in your class. This method will be called everytime a value is set for this field.
In the setter you can change the value of other field as well.
https://www.geeksforgeeks.org/typescript-accessor/
Note: You may have to class instead of interface for the ChatPayload
Upvotes: 0