I'm writing a program that turns two data into a new one. Each of the data comes from an API, so the undefined case must be considered.
but,
item.id === message.sender.userId
A type error occurs in userId in the section.
I want to resolve this type error. I want to solve it by a means that does not change the type or data. Is this possible?
const newMessages = React.useMemo(() => {
if (messages === undefined || userItems === undefined) return [];
return messages.map(message => {
if (message.sender.type === "user" && message.sender.userId) {
const user = userItems.find(item => item.id === message.sender.userId);
if (user) message.sender = { ...message.sender, icon: user.image };
}
return message;
});
}, [messages, userItems]);
Here are the two data I'm getting, and the type of one:
type IMessage = {
sender:
| {
type: "user";
userId: number;
}
| {
type: "admin";
adminId: number;
};
body:
| {
type: "text";
text: "text";
}
| {
type: "image";
text: string;
image: string;
};
};
const messages: IMessage[] =
[
{
"sender": {
"type": "admin",
"adminId": 789
},
"body": {
"type": "image",
"text": "abcde",
"image": "https://imageUrl"
},
},
{
"sender": {
"type": "user",
"userId": 10
},
"body": {
"type": "text",
"text": "Hello!"
},
},
{
"sender": {
"type": "user",
"userId": 13
},
"body": {
"type": "image",
"text": "Hello my friend!",
"image": "https://imageUrl"
},
},
]
const userItems =
[
{
"id": 10,
"name": "kenny",
"image": "https://imageUrl",
"age": 23,
"gender": "M",
},
{
"id": 13,
"name": "Jon",
"image": "https://imageUrl",
"age": 32,
"gender": "M",
}
]
CodePudding user response:
const user = userItems.find(item => item.id === message.sender.userId);
You and i know that this function is going to be called right away, but typescript does not. In general, a callback function could be called at any time, synchronously or asynchronously, and nothing in the type information specifies that. As a result, typescript cannot guarantee that message.sender will still be a user when the callback gets called.
To fix this, assign the value to a const, so typescript can know for sure it won't change.
if (message.sender.type === "user" && message.sender.userId) {
const userId = message.sender.userId
const user = userItems.find(item => item.id === userId);
// ...
P.S:
body:
| {
type: "text";
text: "text";
}
You probably meant to do text: string