No overload matches this call - reactjs

I'm currently working on a school project, and i have this error "No overload matches this call".
The whole error code is here:
No overload matches this call.
Overload 1 of 2, '(props: Omit<any, "initialRouteName" | "children" | "screenOptions" | "defaultScreenOptions"> & DefaultRouterOptions<string> & { children: ReactNode; screenOptions?: BottomTabNavigationOptions | ... 1 more ... | undefined; defaultScreenOptions?: BottomTabNavigationOptions | ... 1 more ... | undefined; }, context?: any): ReactElement<...> | ... 1 more ... | null', gave the following error.
Type '(route: { name: string;}) => { tabBarIcon: (size: number, color: string) => JSX.Element; }' is not assignable to type 'BottomTabNavigationOptions | ((props: { route: RouteProp<ParamListBase, string>; navigation: any; }) => BottomTabNavigationOptions) | undefined'.
Type '(route: { name: string;}) => { tabBarIcon: (size: number, color: string) => JSX.Element; }' is not assignable to type '(props: { route: RouteProp<ParamListBase, string>; navigation: any; }) => BottomTabNavigationOptions'.
Types of parameters 'route' and 'props' are incompatible.
Property 'name' is missing in type '{ route: RouteProp<ParamListBase, string>; navigation: any; }' but required in type '{ name: string; }'.
This error came up when i had to fix some any type errors in CreateScreenOptions:
Be aware that i have tsconfig.json sat to strict due to my teacher.
app.navigator.tsx:
import React from "react";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import { Ionicons } from "#expo/vector-icons";
import { HomeNavigator } from "./home.navigator";
const Tab = createBottomTabNavigator();
const TAB_ICON: {[key: string]: any} = {
Hjem: "md-home",
};
const createScreenOptions = (route: {name: string}) => {
const iconName = TAB_ICON[route.name];
return {
tabBarIcon: ( size: number, color: string) => (
<Ionicons name={iconName} size={size} color={color} />
),
};
};
export const AppNavigator = () => (
<Tab.Navigator
screenOptions={createScreenOptions}
tabBarOptions={{
activeTintColor: "red",
inactiveTintColor: "blue",
}}
>
<Tab.Screen name="Hjem" component={HomeNavigator} />
</Tab.Navigator>
);
home.navigator.tsx:
import React from "react";
import { createStackNavigator } from "#react-navigation/stack";
import { HomeScreen } from "../../features/home/home.screen";
const HomeStack = createStackNavigator();
export const HomeNavigator = () => {
return (
<HomeStack.Navigator headerMode="none">
<HomeStack.Screen name="Home" component={HomeScreen} />
</HomeStack.Navigator>
);
};
home.screen.tsx:
import React from "react";
import { Text, StyleSheet } from "react-native";
export const HomeScreen = () => {
return(
<Text>Hello World!</Text>
)
}

The problem is here:
export const AppNavigator = () => (
<Tab.Navigator
screenOptions={createScreenOptions}
tabBarOptions={{
activeTintColor: "red",
inactiveTintColor: "blue",
}}
>
<Tab.Screen name="Hjem" component={HomeNavigator} />
</Tab.Navigator>
);
More specifically here:
screenOptions={createScreenOptions}
If you check the issue is that the the type of screen options uses a string as key
Check this issue: https://github.com/react-navigation/react-navigation/issues/7855
Also here is another potential issue:
const createScreenOptions = (route: {name: string}) => {
const iconName = TAB_ICON[route.name];
return {
tabBarIcon: ( size: number, color: string) => (
<Ionicons name={iconName} size={size} color={color} />
),
};
};
That function takes one parameter but you are calling it like this:
screenOptions={createScreenOptions}
And maybe you should be calling it like this:
screenOptions={createScreenOptions({name:"some name"})}

Related

Typescript error on SectionList props "is not assignable to type 'AnimatedProps<SectionListProps<any, DefaultSectionT>>' "

I'm using a SectionList with the react-native-modalize lib to display it on a modal. Everything is working, but TypeScript is giving me this error on the 'sectionListProps' prop of the 'Modalize':
Type '{ keyExtractor: (item: SectionListData<Adhesion, DefaultSectionT>) => string; renderItem: ({ item }: { item: SectionListData<Adhesion, DefaultSectionT>; }) => JSX.Element; renderSectionHeader: ({ section: { title } }: ListDataProps) => JSX.Element; persistentScrollbar: true; sections: VehiclesGroup[] | undefined; }' is not assignable to type 'AnimatedProps<SectionListProps<any, DefaultSectionT>>'.
Types of property 'sections' are incompatible.
Type 'VehiclesGroup[] | undefined' is not assignable to type 'readonly WithAnimatedObject<SectionListData<any, DefaultSectionT>>[]'.
Type 'undefined' is not assignable to type 'readonly WithAnimatedObject<SectionListData<any, DefaultSectionT>>[]'.ts(2322)
I tried to import some SectionList types like 'SectionListData' and 'SectionListProps' but the error persists.
The typing and code:
interface VehiclesGroup {
title: string
data: Adhesion[] | null
}
interface ListDataProps {
section: SectionListData<{ title: string }>
}
interface VehicleObject {
plate: string
description: string
type: string
model?: string
}
interface Adhesion {
id: number
icon_color: string
company_id: string
vehicle: VehicleObject
category: string
}
const [vehiclesGroup, setVehiclesGroup] = useState<VehiclesGroup[] | null>([]);
const [searchValue, setSearchValue] = useState<string | ''>('');
const modalizeRef = useRef<Modalize>(null);
// SectionList helpers
const sectionsData = {
sections: vehiclesGroup?.filter((group) => group?.data?.some((item) => {
const validPlate = item.vehicle.plate.toLocaleLowerCase().includes(searchValue);
const validDesc = item.vehicle.description.toLocaleLowerCase().includes(searchValue);
const validCategory = item?.category?.toLocaleLowerCase().includes(searchValue);
return validPlate || validDesc || validCategory;
})),
};
const keyExtractor = (item: SectionListData<Adhesion>) => `${item.id}`;
const renderItem = ({ item }: { item: SectionListData<Adhesion> }) => (
<S.SectionContainer>
<S.SectionItem>
<S.SectionItemIcon bgColor={item.icon_color}>
<FontAwesomeIcon
color={textColors.white}
icon={faCar}
size={25}
/>
</S.SectionItemIcon>
</S.SectionItem>
<S.SectionItem>
<GText
weight={400}
size="lg"
>
{item.vehicle.description}
</GText>
<GText
weight={400}
size="md"
color="secundary"
>
{item.vehicle.plate}
</GText>
</S.SectionItem>
</S.SectionContainer>
);
const renderSectionHeader = ({ section: { title } }: ListDataProps) => (
<S.SectionHeader>
<GText
weight={400}
size="md"
color="secundary"
>
{title}
</GText>
</S.SectionHeader>
);
const memoizedItems = useMemo(() => renderItem, [vehiclesGroup]);
const memoizedHeader = useMemo(() => renderSectionHeader, [vehiclesGroup]);
return (
//...
<Modalize
ref={modalizeRef}
withOverlay={false}
handlePosition="inside"
tapGestureEnabled
modalTopOffset={100}
sectionListProps={{ //Here typescript alerts the error
...sectionsData,
keyExtractor,
renderItem: memoizedItems,
renderSectionHeader: memoizedHeader,
persistentScrollbar: true,
}}
modalStyle={{
paddingTop: 20,
paddingLeft: 30,
paddingRight: 10,
}}
/>
)
"expo": "~45.0.0",
"typescript": "^4.7.4",
"react": "17.0.2",
"react-native": "0.68.2",
"react-native-modalize": "^2.1.1",
"react-native-reanimated": "~2.8.0",

TS2559: Type '{ children: never[]; }' has no properties in common with type 'IntrinsicAttributes & { post?: IPost | undefined; }'

I cant understand whats the probem is.
I have already saw answers to this Error here, I saw one of the issues of others
is a repetition of a function name, and not giving props to a component in the component tree. But I dont think I made those mistakes.
Ill be thankfull for help :)
the Error:
TS2559: Type '{ children: never[]; }' has no properties in common with type 'IntrinsicAttributes & { post?: IPost | undefined; }'.
28 |
29 | {posts}
30 |
| ^^^^
31 |
32 |
33 |
Feed component:
import React, { useEffect, useState } from 'react';
import { Outlet } from 'react-router';
import Post from './Post';
import {List} from './List'
async function getJSON(url: string) {
const res = await fetch(url);
return res.json();
}
export function Feed() {
const [posts, setPosts] = useState([{id: '', title: 'initial state'}])
const [page, setCount] = useState(0);
useEffect(() => {
async function setData() {
setPosts(await getJSON(`./data/posts.json?page=${page}`));
}
setData();
}, [page])
useEffect(() => {
console.log('render Feed');
console.log(posts)
})
return <div style={{backgroundColor:'#FAFAFA'}}>
<List>
{posts}
<Post>
</Post>
</List>
{/* <Post>
</Post> */}
<p>
<button onClick={() => setCount(page + 1)}>Page {page}</button>
</p>
</div>
}
Post component:
import React, { useEffect, useState } from 'react';
import { Link, useParams } from "react-router-dom";
import {List} from './List'
async function getJSON(url: string) {
const res = await fetch(url);
return res.json();
}
interface IPost {
id: string;
title: string;
}
export default function Post({ post }: { post?: IPost }) {
const [numLikes, addLike] = useState(0);
const [dynamicPost, setDynamicPost] = useState({ title: '', id: '' });
const params = useParams();
useEffect(() => {
async function setDynamicData() {
console.log('setDynamicData works')
setDynamicPost(await getJSON(`./data/post.${params.postId}.json`))
}
if (!post) {
setDynamicData();
}
console.log('post is set!')
}, [params.postId, post]);
return <div>
{post ? <div>
<PostBox>
<h2><Link style={{color: 'black', textDecoration: 'none' }} to={`/posts/${post?.id}`}>{post?.title || dynamicPost?.title}</Link></h2>
<p>Num likes {numLikes}</p>
<Like onLike={() => addLike(numLikes + 1)}>
<strong>Bla bla</strong>
</Like>
</PostBox>
</div> :
<div><h2 style={{ color: "red" }}>no posts yet</h2></div>}
</div>
}
interface IPropsLike {
onLike: () => void;
children: JSX.Element;
}
function Like({ onLike, children }: IPropsLike) {
return <button onClick={onLike}>{children}</button>
}
function PostBox({ children }: { children: JSX.Element[] }) {
return <div style={{
border: '4px solid black',
color:"black",
marginBottom: '1em',
width: '100%',
textAlign: 'center'}}>
{children}
</div>
}
The problem is you're giving Post child contents (a text node containing whitespace), but Post doesn't accept child content.
Here's a simpler replication:
interface IPost {
id: string;
title: string;
}
function Post({ post }: { post?: IPost }) {
return <div/>;
}
// v−−−− error here, because of the text node
const x = <Post post={{id: "x", title: "x"}}>
</Post>;
Playground link
Either:
Don't pass children to components that don't accept them:
<Post post={/*...*/} />
Playground link
or
Update Post so it accepts children:
export default function Post({ post, children }: { post?: IPost, children: ReactNode }) {
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^
// v−−−− no error here anymore, the text node is fine
const x = <Post post={{id: "x", title: "x"}}>
</Post>;
...and render the children in Post.
Playground link

React Navigation custom route params and typescript

I have an Error screen that needs to know the error number and a description to display the error and I can't figure out how to tell TS which types are my Error screen custom params. I'm calling my Error screen this way.
navigation.dispatch(
StackActions.replace('Error', {
statusCode: 400,
description: 'Error description',
}),
);
This is my Error screen component. TS complains in route.params
export default function ErrorScreen({ route, navigation }: RootStackScreenProps<'Error'>) {
const { statusCode, description } = route.params; <-- TS error here
// #ts-ignore
const { setClientURL } = appState(({ setClientURL }) => ({
setClientURL,
}));
TS2339: Property 'description' does not exist on type 'Readonly {
key: string; index: number; routeNames: string[]; history?: unknown[]
| undefined; routes: NavigationRoute []; type: string; stale: false;
}>> | undefined>'.
These are my types definitions
import { NavigatorScreenParams } from '#react-navigation/native';
import { NativeStackScreenProps } from '#react-navigation/native-stack';
export type RootStackParamList = {
Root: undefined;
Error: NavigatorScreenParams<ErrorParamList> | undefined;
Notifications: undefined;
Log: undefined;
};
export type RootStackScreenProps<Screen extends keyof RootStackParamList> = NativeStackScreenProps<
RootStackParamList,
Screen
>;
export type ErrorParamList = {
Error: {
statusCode: number;
description: string;
};
};
This is my navigator create code
export default function Navigation({ colorScheme }: { colorScheme: ColorSchemeName }) {
return (
<NavigationContainer
linking={LinkingConfiguration}
theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<RootNavigator />
</NavigationContainer>
);
}
/**
* A root stack navigator is often used for displaying modals on top of all other content.
* https://reactnavigation.org/docs/modal
*/
const Stack = createNativeStackNavigator<RootStackParamList>();
function RootNavigator() {
const colorScheme = useColorScheme();
return (
<Stack.Navigator>
<Stack.Screen
name="Error"
component={ErrorScreen}
options={({ navigation }: RootStackScreenProps<'Error'>) => ({
headerLeft: () => null,
title: 'Ups!...',
headerShadowVisible: false,
headerStyle: {
backgroundColor: '#ffe56d',
},
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 30,
},
gestureEnabled: false,
headerBackVisible: false,
})}
/>
How can I tell TS that for my Error screen route.params can have statusCode and description primitives?

not assignable to type 'IntrinsicAttributes & ContentOutlineProps & ContentBrainstormProps' for dynamically rendered component

I have this page with a <SideBar /> component which dynamically renders different component using setActivePage hook. However, I am getting the following typescript error on the indicated line:
const Content: (({ question_blocks, }: ContentBrainstormProps) => JSX.Element) | (({ outline_blocks }: ContentOutlineProps) => JSX.Element) | (() => JSX.Element)
----------------------------------------------------------------------------------------
Type '{ question_blocks: QuestionBlock[]; } | { outline_blocks: OutlineBlock[]; } | {}' is not assignable to type 'IntrinsicAttributes & ContentBrainstormProps & ContentOutlineProps'.
Property 'outline_blocks' is missing in type '{ question_blocks: QuestionBlock[]; }' but required in type 'ContentOutlineProps'.ts(2322)
ContentOutline.tsx(7, 3): 'outline_blocks' is declared here.
const Draft = () => {
const [draftData, setDraftData] = useState<Document>(defaultDraftData);
const [activePage, setActivePage] = useState<
'One' | 'Two' | 'Three'
>('One');
const contents = {
Brainstorm: {
Content: ContentBrainstorm,
props: { question_blocks: draftData.question_blocks }, // question_blocks: QuestionBlock[]
},
Outline: {
Content: ContentOutline,
props: { outline_blocks: draftData.outline_blocks }, // outline_blocks" OutlineBlock[]
},
Write: {
Content: ContentWrite,
props: {},
},
};
const { Content, props } = contents[activePage];
useEffect(() => {
axios.get(apiRoute)
.then(function (response) {
setDraftData(response.data);
});
}
}, []);
return (
<div className="bg-offwhite flex flex-col">
<SideBar activePage={activePage} setActivePage={setActivePage} />
<LayoutApp>
<Header header={title} draftId={draftId} />
<Content {...props} /> // <-----ERROR HERE----->
</LayoutApp>
<UtilBar />
</div>
);
};
ContentOutline.tsx
type ContentOutlineProps = {
outline_blocks: OutlineBlock[];
};
export const ContentOutline = ({ outline_blocks }: ContentOutlineProps) => (
<LayoutContent>
<HeaderText text="Step 2: Organize your ideas and arguments into different paragraphs" />
<OutlineCardList outline_blocks={outline_blocks} />
</LayoutContent>
);
Define the types ContentOutlineProps, ContentBrainstormProps as following
type ContentOutlineProps = {
outline_blocks?: OutlineBlock[];
question_blocks?: OutlineBlock[];
};
type ContentBrainstorm = {
outline_blocks?: OutlineBlock[];
question_blocks?: OutlineBlock[];
};

Typing a React Component Factory Function

Given the type
type EnumerableComponentFactory = <C, I>(config: {
Container: React.ComponentType<C>;
Item: React.ComponentType<I>;
}) => React.FC<{ items: I[] }>;
with the following implementation
const Enumerable: EnumerableComponentFactory =
({ Container, Item }) =>
({ items }) =>
(
<Container>
{items.map((props, index) => (
<Item key={index} {...props} />
))}
</Container>
);
and intended use
const UnorderedList = Enumerable({
Container: ({ children }) => <ul>{children}</ul>,
Item: ({ title }: { title: string }) => <li>{title}</li>,
});
<UnorderedList items=[{title: "Something"}] />
I'm observing the following TypeScript error
Type '{ children: Element[]; }' is not assignable to type 'C'.
'C' could be instantiated with an arbitrary type which could be unrelated to '{ children: Element[]; }'.ts(2322)
which leads me to my question: What type constraints do I need to set up to resolve this error?
I've tried to change the type as follows:
type EnumerableComponentFactory = <C extends { children?: Element[] }, I>(config: {
Container: ComponentType<C>;
Item: ComponentType<I>;
}) => (props: { items: I[] }) => ReturnType<FC<I>>;
but this produces an even more cryptic error message, which I'm going to omit for the sake of brevity.
P.S. The function itself actually does exactly what's expected. It's just the compiler that trips up.
Is it necessary to keep C generic parameter?
import React, { FC, ComponentType, PropsWithChildren } from "react";
type EnumerableComponentFactory = <I>(config: {
// or Container: FC<{ children: JSX.Element[] }>;
Container: FC<PropsWithChildren<object>>;
Item: ComponentType<I>;
}) => FC<{ items: I[] }>;
const Enumerable: EnumerableComponentFactory =
({ Container, Item }) =>
({ items }) =>
(
<Container>
{items.map((props, index) => (
<Item key={index} {...props} />
))}
</Container>
);
const UnorderedList = Enumerable({
Container: ({ children }) => <ul>{children}</ul>,
Item: ({ title }: { title: string }) => <li>{title}</li>,
});
const result = <UnorderedList items={[{ title: "Something" }]} />;
I was able to alter your code to make it work, while also accepting other props to be passed to the container:
type EnumerableComponentFactory = <C, I>(config: {
Container: React.ComponentType<C & { children: React.ReactNode[] }>;
Item: React.ComponentType<I>;
}) => React.ComponentType<C & { items: I[] }>;
const Enumerable: EnumerableComponentFactory = ({ Container, Item }) => (
props
) => (
<Container {...props}>
{props.items.map((props, index) => (
<Item key={index} {...props} />
))}
</Container>
);
Which allows for e.g. this:
const ContainerWithBorder: React.ComponentType<{ color: string }> = (props) => (
<div style={{ border: `2px solid ${props.color}` }}>
<ul>{props.children}</ul>
</div>
);
const ComplexList = Enumerable({
Container: ContainerWithBorder,
Item: ({ title }: { title: string }) => <li>{title}</li>
});
<ComplexList items={[{ title: "Something" }]} color="red" />
The ComplexList component comes with typing/intellisense for the color property.
A playground with the original and ComplexList example can be found here.

Resources