打字稿:基于另一个属性的属性

时间:2020-03-31 16:48:35

标签: typescript conditional-types

我遇到了嵌套类型的情况,我想要实现的是基于另一个属性的值来指定属性。

在HTML中,我循环API的响应,并根据接收到的类型值,希望有一个不同的选项值。

例如:如果我收到类型为“ articles”的回复,我希望将OptionArticles作为ChatOptions。

有解决方案吗?

这是代码:

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;
}

谢谢。

2 个答案:

答案 0 :(得分:2)

您可以使用conditional types来强制chatPayload中的类型与chatPayload.options中的类型相同。

ChatPayload可以将API中的“类型”作为类型参数:

interface ChatPayload<Type extends ChatTypes> {
    type: Type;
    options: Type extends "articles" ? OptionArticles : Type extends "params" ? OptionParams : OptionText ;
    confidence?: number;
    gotAllParams?: boolean;
}

您可以根据API响应中字段的值切换类型:

// 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")
}

强制转换有点难看,但是您必须使用强制转换才能将未类型化的API响应转换为您自己的类型之一。

为了进一步安全,您可以使用JSON验证程序来确保从API获得的响应符合您的期望。

Typescript playground

答案 1 :(得分:0)

也许您可以在课程中为字段使用设置器。每当为此字段设置值时,都会调用此方法。

在设置器中,您还可以更改其他字段的值。

https://www.geeksforgeeks.org/typescript-accessor/

注意:对于ChatPayload,您可能必须分类而不是接口