'how can i give type in getServerSideProps of Nextjs with typescript?
I'm using NextJs + TypeScript to make a little clone project, but I got a problem with type in getServerSideProps
.
As you can see, in getServerSideProps
, I am fetching data using with context.query
.
But some error message is not fixed and I don't understand why that error appears.
The error message is this.
Type 'string[]' cannot be used as an index type.ts(2538)
Type 'undefined' cannot be used as an index type.ts(2538)
const genre: string | string[] | undefined
How can I fix this type problem?
import Head from "next/head";
import Nav from "../components/Nav/Nav";
import Header from "../components/Header/Header";
import Results from "../components/Results/Results";
import requests from "../utils/requests";
import { GetServerSideProps } from "next";
type HomeProps = {
results: {}[];
};
export default function Home({ results }: HomeProps) {
console.log(results);
return (
<div>
<Results results={results} />
</div>
);
}
export const getServerSideProps: GetServerSideProps = async (context) => {
const genre = context.query.genre
const response = await fetch(
`https://api.themoviedb.org/3${
requests[genre]?.url {/*this is problem line*/}
|| requests.fetchTopRated.url
}`
);
const data = await response.json();
return {
props: { results: data.results },
};
};
Solution 1:[1]
Since the type of genre
can be string
or string[]
(or undefined), it can not be used to index requests
without being narrowed down to string
via the use of an if
statement:
if (typeof genre === 'string') {
// Typescript now knows it is a string
const response = await fetch(
`https://api.themoviedb.org/3${
requests[genre]?.fetchTopRated.url {/*this is problem line*/}
|| requests.fetchTopRated.url
}`
);
const data = await response.json();
return {
props: { results: data.results },
};
} else if (typeof genre == 'object'){
// handle case where it is an array
} else {
// genre is undefined
}
Solution 2:[2]
When you receive params via context, the value could be either string
or string[]
(or undefined) so you need to cast. It could be a single genre or multiple genres in the URL.
?genre=film
or ?genre=film&genre=music
For you case, simply cast as string:
const genre = context.query.genre as string;
UPDATE
As per your comments, the first issue that you raised in the question was actually about casting to string
as above.
The second issue, which you should not actually be seeing and must be a TS or module config issue, is related to trying to accessing a key as string by index on your vanilla object exported from "../utils/requests";
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ fetchTrending: { title: string; url: string; }; ...
Your data object has literal key names:
// ../utils/requests
export default {
fetchTrending: {
title: "Trending",
url: /trending/all/week?api_key=${API_KEY}&language=en-US,
},
fetchTopRated: {
title: "Top Rated",
url: /movie/top_rated?api_key=${API_KEY}&language=en-US,
},
};
Rather define the type like this:
export interface IRequest {
[name: string]: {
title: string;
url: string;
};
}
const data: IRequest = {
fetchTrending: {
title: "Trending",
url: `/trending/all/week?api_key=${API_KEY}&language=en-US1`
},
fetchTopRated: {
title: "Top Rated",
url: `/movie/top_rated?api_key=${API_KEY}&language=en-US`
}
};
export default data;
or you could use a Record to have strongly typed keys:
type RequestNames = "fetchTrending" | "fetchTopRated";
export const records: Record<
RequestNames,
{
title: string;
url: string;
}
> = {
fetchTrending: {
title: "Trending",
url: `/trending/all/week?api_key=${API_KEY}&language=en-US1`
},
fetchTopRated: {
title: "Top Rated",
url: `/movie/top_rated?api_key=${API_KEY}&language=en-US`
}
};
Solution 3:[3]
You can use like this;
type PageProps = {
isAuthanticated: boolean,
categories?: CategoryType[]
}
export const getServerSideProps: GetServerSideProps = async (context) => {
const _props: PageProps = {
isAuthanticated: auth,
categories: data.results
}
return { props: _props }
};
const Category: NextPage<PageProps> = (props) => {
return(
...
)
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | David Deutsch |
Solution 2 | |
Solution 3 | MehmetDemiray |