Type error: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type
hellojennifertran opened this issue · 5 comments
Am I missing something? I'm on part II and get this when I run npm run build
(note: it runs okay with npm run dev
):
./components/TypeCard.tsx:21:35
Type error: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ Dog: { image: { url: string; }; photographer: { name: string; url: string; }; }; Cat: { image: { url: string; styles: { backgroundPosition: string; }; }; photographer: { name: string; url: string; }; }; Rabbit: { ...; }; ... 4 more ...; Barnyard: { ...; }; }'.
No index signature with a parameter of type 'string' was found on type '{ Dog: { image: { url: string; }; photographer: { name: string; url: string; }; }; Cat: { image: { url: string; styles: { backgroundPosition: string; }; }; photographer: { name: string; url: string; }; }; Rabbit: { ...; }; ... 4 more ...; Barnyard: { ...; }; }'.
19 | className="w-40 h-40 flex-shrink-0 mx-auto rounded-full bg-cover bg-no-repeat"
20 | style={{
> 21 | backgroundImage: `url(${ANIMAL_TYPES[type.name].image.url})`,
| ^
22 | backgroundPosition: "center",
23 | ...ANIMAL_TYPES[type.name].image.styles,
24 | }}
Hmm, I tried reproducing this issue by cloning the repository, changing the branch to part-1
and following the steps in the second blog post, but I was unable to reproduce it.
Are you able to provide a link to the project's repository?
Double check that TypeCardProps
interface is defined correctly in components/TypeCard.tsx
:
export interface TypeCardProps {
className?: string;
type: AnimalType;
}
And AnimalType
interface in shared/interfaces/petfinder.interface.ts
:
export interface AnimalType {
id?: string;
name: any;
coats: string[];
colors: string[];
genders: string[];
breeds?: AnimalTypeBreed[];
_links: {
self: {
href: string;
};
breeds: {
href: string;
};
};
}
Also log the types returned from the Petfinder API to verify that the application receives valid data (in pages/index.tsx
):
console.log(types);
return {
props: {
types:
types.length > 0
? types.map((type) => ({
...type,
id: type._links.self.href.match(/\/types\/([\w-]+)$/)[1],
}))
: types,
},
};
If everything above looks good, then off the top of my head, one way you can solve this problem is to specify that type.name
can be a key of the type of ANIMAL_TYPES
, like so:
backgroundImage: `url(${ANIMAL_TYPES[type.name as keyof typeof ANIMAL_TYPES].image.url})`
But then, the TS compiler might complain about the remaining lines in the file that access ANIMAL_TYPES[type.name]
.
So you can also try this solution, which explicitly implements an interface for the ANIMAL_TYPES
enum (in enums/index.ts
):
interface AnimalTypesEnum {
[key: string]: {
image: {
url: string;
styles?: {
backgroundPosition?: string;
objectPosition?: string;
};
};
photographer: {
name: string;
url: string;
};
};
}
export const ANIMAL_TYPES: AnimalTypesEnum = {
// ...
};
Thanks for your response!
For part 1, I ran the command npx create-next-app@latest --ts to automatically scafford a Next.js project with TypeScript then proceeded with the steps in your blog (so I didn't clone the repo). Maybe something went wrong along the way there, but here's the repo: https://github.com/hellojennifertran/petfinder-nextjs
Don't worry about spending effort on this though! I can try cloning your repo and go from there (although I do get a 401 when I do this, despite having the correct creds). But will work through that later.
@hellojennifertran Ah, I see what the cause is. My tsconfig.json
must be outdated since the strict
compiler option is not set to true
.
So the fix here is to explicitly annotate the ANIMAL_TYPES
enum:
(enums/index.ts
)
interface AnimalTypesEnum {
[key: string]: {
image: {
url: string;
styles?: {
backgroundPosition?: string;
objectPosition?: string;
};
};
photographer: {
name: string;
url: string;
};
};
}
export const ANIMAL_TYPES: AnimalTypesEnum = {
// ...
};
I'll push a fix for this. Thanks for pointing this out!
Hey,
Thanks @kenchandev! I had the same issue and your suggestions in comment fixed it
- Adding the
AnimalTypesEnum
toenums/index.ts
- Updating
components/TypeCard.tsx
to be a key of typeANIMAL_TYPES
fixed it
I did have another type issue after this though with pages/_app.tsx
and adding it here in case anyone hits the same issue.
1 | import "../styles/globals.css"; // If you have not yet installed TailwindCSS in the Next.js application, then consult the documentation for installing TailwindCSS in a Next.js application: https://tailwindcss.com/docs/guides/nextjs.
2 |
> 3 | function App({ Component, pageProps }) {
| ^
4 | return (
5 | <div className="bg-gray-100 py-8 min-h-screen">
6 | <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
Importing AppProps
and setting the type fixed it
import "../styles/globals.css";
import type { AppProps } from 'next/app'
function App({ Component, pageProps }: AppProps) {
It's all working now with npm run build
Moving forward, the tutorial series will make use of strict: true
in the TypeScript configuration so that the project aligns as if it was scaffolded with create-next-app
. The blog posts, and along with the code in their respective branches, have been updated with the changes needed for strict: true
.