Martin Rützy
Martin Rützy

Reputation: 525

I am confused about this simple component in React with TypeScript

I'm new in TypeScript and in this simple example I've created a component to fetch data from a fake API and show them in a map iteration:

import React, { FC, useState } from 'react';

const GetData = (): Promise<[]> => {
  return fetch('https://randomuser.me/api/?results=5')
         .then((response: any) => response.json())
         .then((data: any) => data.results);
}

const App: FC<{}> = () => {
  const [users, setUsers] = useState<[]>([]);

  const getUsers = (): void => {
    GetData().then((data: []) => setUsers(data));
  }

  return (
    <div>
      {
        <ul>
          {
            users.map((item: any, index: number) => (
              <li key={`user-${index}`}>{`${item.name.first} {item.name.last}`}</li>
            ))
          }
        </ul>
      }
      <button onClick={getUsers}>Load</button>
    </div>
  )
}

export default App;

This code works well ! but I'm not sure about true of my codes... In this example I've :any type for functions input (in promise chain eg.) so, is it correct to this example? am I able to use many of any type in arguments when I'll have a nested array in output?

and the second one, I didn't add type with : for GetData, but that is a const and I should declare them something like this:

const age: number = 40;

but I didn't get any error?

Thank you

Upvotes: 2

Views: 278

Answers (3)

Mohammad Esmaeilzadeh
Mohammad Esmaeilzadeh

Reputation: 160

When you are using Promise generic to define one, you shouldn't add type for callback functions into chain. for example write your chain like this:

const GetData = (): Promise<User[]> => {
    return fetch('https://randomuser.me/api/?results=5')
        .then((response) => response.json())
        .then((data) => data.results);
}

And for second one question about const age: number = 40; when you define a const and assign function to that, means you are create a function and TypeScript considers it will be a function and not a primitive value, therefore, you shouldn't add type for const after that name. but when you are set something like this: const age: number = 40; the above code means, your are defining a primitive value and should set type after name.

Upvotes: 1

Linda Paiste
Linda Paiste

Reputation: 42160

When you use any you miss out on most of typescript's error-finding abilities. You are basically saying, "trust me, this is fine" since any is assignable to any type.

There are a few places that we can improve your types and also a few types that are inaccurate. Promise<[]> actually means that this is a promise of the empty array []. You want it to return an array of users: Promise<User[]>.

You might have this User object typed somewhere else in your app already. Here I am just defining the properties that we need for this component.

interface User {
    name: {
        first: string;
        last: string;
    }
}

Calling fetch returns Promise<Response> where Response is a built-in object type that supports the .json() method. So instead of (response: any) you are better off just doing (response) and using the inferred type. That .json() method returns Promise<any>, so the inferred type for data is any. You can choose to assert at this point that data is an object with a property results containing an array of User objects, but you can also just stick with the inferred any and rely on your function's return type to assert that.

const GetData = (): Promise<User[]> => {
    return fetch('https://randomuser.me/api/?results=5')
        .then((response) => response.json())
        .then((data) => data.results);
}

Now to the component. Our state is an array of User, not an empty array.

const [users, setUsers] = useState<User[]>([]);

Once you change that, you can remove the types from (data: []) and (item: any, index: number). You generally don't need to assert types in a callback when you have proper types higher up in the chain. When you call users.map, the item is already known to have type User because users is typed as User[].

Typescript Playground Link

Upvotes: 1

Quentin
Quentin

Reputation: 943142

Using any is a brute force approach that discards all the benefits of using TypeScript on the first place. It works, but isn’t recommended.

Given const age = 40, TypeScript knows that you are assigning a number. The expression on the right-hand side cannot be anything other than a number. It can infer the type from that so you don’t need to be explicit.

Upvotes: 0

Related Questions