下面有一个示例,它是我实际代码的一个非常简化的版本。
我有一个类型,可以是一个接口,也可以是另一个类似的类型:
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
这是一个打字稿操场
现在,在我的代码中,当我试图简单地检查"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")
}
})
但是打字本给我带来了一个错误
Property 'emoji' does not exist on type '{ text?: string | undefined; }'.
所以我的问题是,我怎么才能让if("emoji" in chat.configs && chat.configs.emoji)
不长得可笑呢?
发布于 2022-12-02 03:09:46
类型谓词可能有助于简化事情:https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
function hasDefinedEmoji(chat: Chat): chat is ChatEmoji & {configs: {emoji: string}} {
return chat.type === "emoji" && Boolean(chat.configs.emoji);
}
if(hasDefinedEmoji(chat)){
console.log("Has an emoji", chat.configs.emoji) // works
}
缺点是你可以在谓词函数中犯一个错误,然后朝自己的脚开枪。你可以这样做,打字稿一点也不好看:
function hasDefinedEmoji(chat: Chat): chat is ChatEmoji & {configs: {emoji: string}} {
return true;
}
发布于 2022-12-03 22:46:10
只需为助手文件中的每个类型(如果需要)定义一个类型谓词:
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));
https://stackoverflow.com/questions/74650451
复制相似问题