如何快速检查Typescript中的条件对象类型上是否存在对象属性?

6kkfgxo0  于 2022-12-05  发布在  TypeScript
关注(0)|答案(2)|浏览(219)

下面的例子是我的实际代码的一个非常简化的版本。
我有一个类型,可以是接口,也可以是其他类型,如下所示:

interface ChatBase {
    roomId?: string
    type: "message" | "emoji"
    configs: unknown
}
interface ChatMessage extends ChatBase {
    type: "message",
    configs:{
        text?: string
    }
}
interface ChatEmoji extends ChatBase {
    type: "emoji",
    configs: {
        emoji?: string
    }
}
type Chat =  ChatMessage | ChatEmoji

这是一个 typescript 游戏场
现在在我的代码中,当我试图简单地检查“emoji”是否在configs中定义时,它使它变得超级复杂,肯定有一个更简单的方法吗?

const chats: Chat[] = [
    { type: "message", configs: { text: "string" } },
    { type: "emoji", configs: { emoji: "string" } }
]

chats.map(chat=>{
    if(chat.configs.emoji){ // <=== THROWS ERROR SHOWN BELOW
        console.log("Has an emoji")
    }
    if("emoji" in chat.configs && chat.configs.emoji){ // <= Works but ridiculously long
        console.log("Has an emoji")
    }
    if(chat.type === "emoji" && chat.configs.emoji){ // <= Works but sometimes I test for shared properties
        console.log("Has en emoji")
    }
})

但是 typescript 给我带来了一个错误

Property 'emoji' does not exist on type '{ text?: string | undefined; }'.

所以我的问题是,我怎样才能让if("emoji" in chat.configs && chat.configs.emoji)不那么长呢?

wqsoz72f

wqsoz72f1#

类型 predicate 可能有助于简化事情:https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
第一个
缺点是你可能会在 predicate 函数中犯错误,从而搬起石头砸自己的脚。你可以这样做,而typescript不会眨一下眼睛:

function hasDefinedEmoji(chat: Chat): chat is ChatEmoji & {configs: {emoji: string}} {
    return true;
}
j2qf4p5b

j2qf4p5b2#

只需在帮助器文件中为每个类型定义一个类型 predicate (如果需要):

const isChatEmoji = (chat: ChatBase): chat is ChatEmoji => chat.type === "emoji";
const isChatMessage = (chat: ChatBase): chat is ChatMessage => chat.type === "message";

然后,您可以执行以下操作:

chats.filter(isChatEmoji).forEach(chat => console.log(chat.configs.emoji));

相关问题