Double map in React+Typescript - reactjs

Maybe I'm missing something, but how should I properly double map in this case? Bcs I have error on secon map : Property 'map' does not exist on type '{ departure: { code: string; name: string; dateTime: string; }; destination: { code: string; name: string; dateTime: string; }; duration: string; }
const [result, setResult] = useState<ConversionData[]>([]);
type ConversionData = {
uuid: string;
airlinesCode: string;
price: {
amount: number;
currency: string;
};
bounds: {
departure: {
code: string;
name: string;
dateTime: string;
};
destination: {
code: string;
name: string;
dateTime: string;
};
duration: string;
};
};
useEffect(() => {
const api = async () => {
const data = await fetch("http://localhost:3001/flights").then((res) =>
res.json()
);
setResult(data);
console.log(result);
};
api();
}, []);
return (
<div className="App">
<h1>
{result?.map((value) => {
console.log(value)
return (
<div>
<div>{value.price.amount}</div>
{value.bounds.map((newvalue:any)=>{
<div>{newvalue.departure.name}</div>
})}
</div>
);
})}
</h1>
</div>
);
what I need to map
I've searched the internet for something similar, but I've hit the starting point, and I need to get to bounds -> departure -> name

Bounds in your type ConversionData is object. But at you data screenshot bounds should be array.
bounds: Array<{
departure: {
code: string;
name: string;
dateTime: string;
};
destination: {
code: string;
name: string;
dateTime: string;
};
duration: string;
};
}>;

Related

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type - TypeScript Error

const [basicDetails, setBasicDetails] = useState({
companyName: "",
pocName: "",
pocEmail: "",
pocMobile: "",
businessCard: { file: "", type: "", url: "" },
companyBaseAddress: [defaultAddress]
});
const [errorMessage, setErrorMessage] = useState({
companyName: "",
pocName: "",
pocEmail: "",
pocMobile: "",
businessCard: { file: "", type: "", url: "" },
companyBaseAddress: [defaultAddress]
});
const validation = () => {
Object.keys(errorMessage).map((field => basicDetails[field] === "" ?
setErrorMessage(prevState => ({ ...prevState, [field]: "Can not be Empty" })) : null));
};
Error is -> Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ companyName: string; pocName: string; pocEmail: string; pocMobile: string; businessCard: { file: string; type: string; url: string; }; companyBaseAddress: { line1: string; line2: string; city: string; region: string; zip_code: string; country: string; }[]; }'.
No index signature with a parameter of type 'string' was found on type '{ companyName: string; pocName: string; pocEmail: string; pocMobile: string; businessCard: { file: string; type: string; url: string; }; companyBaseAddress: { line1: string; line2: string; city: string; region: string; zip_code: string; country: string; }[]; }'
I had this issue in the past as well. You may want to try to create an interface for both your states basicDetails and errorMessages:
interface BasicDetailsInterface {
[key: string]: string,
companyName: string,
pocName: string,
pocEmail: string,
// continue for other props
}
interface ErrorMessageInterface {
[key: string]: string,
companyName: string,
pocName: string,
pocEmail: string,
// continue for other props
}
And then update the declaration of your states to reflect the interfaces you just created:
const [basicDetails, setBasicDetails] = useState<BasicDetailsInterface>({
const [errorMessage, setErrorMessage] = useState<ErrorMessageInterface>({

No overload matches this call. Overload 1 of 2, '(...items: ConcatArray<never>[]): never[]', gave the following error

Making recursive comment structure,
I use the following function.
interface IComment {
_id: string;
body: string;
forum_id: string;
parent_comment_id: string;
author_name: string;
author_id: string;
authorPic: string;
votes: number;
h_voted: number;
created_at: string;
updated_at: string;
}
const getCommentsWithChildren = (comments: IComment[]) => {
const commentsWithChildren = comments.map((comment) => ({
...comment,
children: [],// This is new empty child array
}));
commentsWithChildren.forEach((childComment) => {
const { parent_comment_id } = childComment;
if (parent_comment_id) {
const parent = commentsWithChildren.find(
(comment) => parent_comment_id === comment._id
);
if (parent !== undefined) {
parent.children = parent.children.concat(childComment);// This part make the error
}
}
});
return commentsWithChildren.filter(
({ parent_comment_id, body, children }) =>
parent_comment_id === null && (body !== null || children.length > 0)
);
};
As you can see,
to make a child object array,
add 'children: []'
and then in recursive function
add child by
'parent.children = parent.children.concat(childComment);'
above line cause the error
'No overload matches this call. Overload 1 of 2, '(...items: ConcatArray[]): never[]', gave the following error.
Argument of type '{ children: never[]; _id: string; body: string; forum_id: string; parent_comment_id: string; author_name: string; author_id: string; authorPic: string; votes: number; h_voted: number; created_at: string; updated_at: string; }' is not assignable to parameter of type 'ConcatArray'.
Type '{ children: never[]; _id: string; body: string; forum_id: string; parent_comment_id: string; author_name: string; author_id: string; authorPic: string; votes: number; h_voted: number; created_at: string; updated_at: string; }' is missing the following properties from type 'ConcatArray': length, join, slice
Overload 2 of 2, '(...items: ConcatArray[]): never[]', gave the following error.
Argument of type '{ children: never[]; _id: string; body: string; forum_id: string; parent_comment_id: string; author_name: string; author_id: string; authorPic: string; votes: number; h_voted: number; created_at: string; updated_at: string; }' is not assignable to parameter of type 'ConcatArray'.'
maybe 'children: []' is never type...
In typescript, how to solve this problem?
thanks very much for reading this writing.
When you create your empty array within commentsWithChildren you create an array of never[] - which is what cannot be concatenated.
You should explicitly set the type of commentsWithChildren or the array you set to commentsWithChildren.children.
Thank your N.J.Dawson!!
I solved the above error.
The following code is that.
interface IComment {
_id: string;
body: string;
forum_id: string;
parent_comment_id: string;
author_name: string;
author_id: string;
authorPic: string;
votes: number;
h_voted: number;
created_at: string;
updated_at: string;
}
interface ICommentWithChildren extends IComment {
children: IComment[];
}
const getCommentsWithChildren = (comments: IComment[]) => {
const commentsWithChildren: ICommentWithChildren[] = comments.map(
(comment) => ({
...comment,
children: [],
})
);
commentsWithChildren.forEach((childComment) => {
const { parent_comment_id } = childComment;
if (parent_comment_id) {
const parent = commentsWithChildren.find(
(comment) => parent_comment_id === comment._id
);
if (parent !== undefined) {
parent.children = parent.children.concat(childComment);
}
}
});
return commentsWithChildren.filter(
({ parent_comment_id, body, children }) =>
parent_comment_id === null && (body !== null || children.length > 0)
);
};
added part is
interface ICommentWithChildren extends IComment {
children: IComment[];
}
and modified part is
const commentsWithChildren: ICommentWithChildren[]
thanks again!!

type of custom object in typescript

I'm new to typescript and I created this object:
const initialState = {
title: {
value: "",
error: false
},
amount: {
value: 0,
error: false
},
type: "Food",
time: new Date()
}
I want to use is as initial state of a useState. therefore I want to now what I need to passe as type to my useState.
const [Form, setForm] = useState< "what should come here?" >(initialState);
thanks in advance,
interface IState {
title: {
value: string;
error: boolean;
};
amount: {
value: number;
error: boolean;
};
type: string;
time: Date;
}
const [Form, setForm] = useState<IState>(initialState);
You could do something like this:
interface SomeName {
value: string;
error: boolean;
}
interface IState {
title: SomeName;
amount: SomeName;
type: string;
time: Date;
}
const initialState: IState = {
title: {
value: "",
error: false
},
amount: {
value: 0,
error: false
},
type: "Food",
time: new Date()
}
const [Form, setForm] = useState<IState>(initialState);

Getting Typescript Error while adding object to array using useState in React

Result type prop is defined as follows. CalendarProp, ContactProp,... are predefined and all have different types.
type ResultProp =
| { type: "calendar", data: CalendarProp }
| { type: "contact", data: ContactProp }
| { type: "dropbox", data: DropboxProp }
| { type: "slack", data: SlackProp }
| { type: "tweet", data: TweetProp }
Calendar Prop
interface CalendarProp {
id: string,
title: string,
invitees: string,
date: string,
matching_terms: Array<string>
}
ContactProp type
interface ContactProp {
id: string,
name: string,
company: string,
emails: Array<string>,
phones: Array<string>,
last_contact: string,
matching_terms: Array<string>
}
All the props have a different type.
Component maintaining a result array is defined below. I am getting Typescript error while adding object to result array using useState hook.
Here calendarData.calendar, ... is an array of json object.
const SearchResults: React.FC<QueryProp> = (props) => {
const query = props.query;
const [result, setResult] = useState<Array<ResultProp>>([]);
useEffect(() => {
if (query.length > 0){
const files = [
{
type: "calendar",
data: calendarData.calendar
},
{
type: "contact",
data: contactData.contacts
},
{
type: "dropbox",
data: dropboxData.dropbox
},
{
type: "slack",
data: slackData.slack
},
{
type: "tweet",
data: tweetData.tweet
}
];
for(const file of files){
for(const d of file.data){
if (d.matching_terms.includes(query)) {
switch(file.type) {
case "calendar":
setResult([...result, { type: "calendar", data: d }]); // Error here
break;
}
}
}
}
}
return () => {
setResult([]);
}
}, [query])
return (
<div className="search-results">
{/* {result.map((r, index) => {
return <Cardview key={index} {...r} />
})} */}
</div>
)
}
I get the following error message:
Argument of type '({ type: "contact"; data: ContactProp; } | { type: "dropbox"; data: DropboxProp; } | { type: "slack"; data: SlackProp; } | { type: "tweet"; data: TweetProp; } | { ...; })[]' is not assignable to parameter of type 'SetStateAction<ResultProp[]>'.
Type '({ type: "contact"; data: ContactProp; } | { type: "dropbox"; data: DropboxProp; } | { type: "slack"; data: SlackProp; } | { type: "tweet"; data: TweetProp; } | { ...; })[]' is not assignable to type 'ResultProp[]'.
Type '{ type: "calendar"; data: { id: string; title: string; invitees: string; matching_terms: string[]; date: string; } | { id: string; name: string; company: string; emails: string[]; phones: string[]; matching_terms: string[]; last_contact: string; } | { ...; } | { ...; } | { ...; } | { ...; }; }' is not assignable to type 'ResultProp'.
Types of property 'data' are incompatible.
Type '{ id: string; title: string; invitees: string; matching_terms: string[]; date: string; } | { id: string; name: string; company: string; emails: string[]; phones: string[]; matching_terms: string[]; last_contact: string; } | { ...; } | { ...; } | { ...; } | { ...; }' is not assignable to type 'CalendarProp'.
Type '{ id: string; name: string; company: string; emails: string[]; phones: string[]; matching_terms: string[]; last_contact: string; }' is missing the following properties from type 'CalendarProp': title, invitees, date
Here you test that file coming from files match the calendar type. But you never said to TypeScript the type of files. It's not sure for him what d really is so it can be CalendarProp or ContactProp or... You have 2 solutions to fix that:
Declare the type of files:
const files: ResultProp[] = [
...
In this case, if file.type is "calendar", then TypeScript can deduce that data is of type CalendarProp.
Cast the value of d to CalendarProp:
setResult([...result, { type: "calendar", data: d as CalendarProp }]);

How to use React + TypeScript to render components by looping through an array?

I have tried to loop over items of an array but I am missing some typing for my components in TypeScript. I have tried Card<any or Card<IProps> with the interface being defined below (not being used below).
This is the error I've gotten so far
I get this error.
Type '{ key: number; card: { name: string; image: string; id: number;
}; }' is not assignable to type 'IntrinsicAttributes & { children?:
ReactNode; }'.
Property 'card' does not exist on type 'IntrinsicAttributes & { children?: ReactNode; }'.
I am curious to learn what it is exactly that I am missing here?
const cards = [
{
name: "a",
image: "red",
id: 1
},
{
name: "b",
image: "blue",
id: 2
},
{
name: "c",
image: "green",
id: 3
}
];
interface IProps {
card: {
name: string;
image: string;
id: number;
};
key: string;
}
...(Stateless component logic here)...
const renderCards = () => {
return cards.map(card => {
return <Card key={card.id} card={card} />;
});
};
return (
<div>
<CardContainer>{renderCards()}</CardContainer>
</div>
);
I would need to see your Card component implementation, but I am guessing the following should helpĀ :
interface ICard {
name: string;
image: string;
id: number;
}
interface IProps {
card: ICard;
key: string;
}
const cards: ICard[] = [
{
name: "a",
image: "red",
id: 1,
},
{
name: "b",
image: "blue",
id: 2,
},
{
name: "c",
image: "green",
id: 3,
},
];
const Card: React.FC<{ card: ICard }> = ({ card }) => {
return <div>{card.name}</div>;
};
const renderCards = () => {
return cards.map(card => {
return <Card key={card.id} card={card} />;
});
};
return (
<div>
<CardContainer>{renderCards()}</CardContainer>
</div>
);
Ensure you're including a children param in the interface of your Props
e.g.
interface CardProps {
card:{
name: string;
image: string;
id: number;
},
children: React.ReactNode
}
const Card= ({
card,
children,
}: CardProps) => {
// and do whatever you like with `card` prop here
return ( {children})
}

Resources