Búsqueda de sitios web

reactjs - React Typescript cómo pasar props con tipos


Tratando de mejorar con Typescript en React

Tengo una aplicación súper simple donde tengo App.tsx con un useState para un arreglo de objetos

import List from './components/List';

interface IState{
  name: string
  age: number
}

function App() {

  const [people, setpeople] = useState<IState[]>([
    {
      name: 'Chris',
      age: 20
    },
    {
      name: 'John',
      age: 28
    },
    {
      name: 'Paul',
      age: 23
    }
  ])

  return (
    <div className="App">
      <List people={people}/>
    </div>
  );
}

export default App;

Quiero pasar esto como una prop a otro componente List.tsx.

interface IProps{
    name: string
    age: number
  }

const List = (people:IProps[]) => {
    return (
        <div>
            {people.map(person => (
                <h2>{person.name}</h2>
            ))}
        </div>
    );
};

export default List;

Tengo tipos para el objeto en App.tsx y estoy tratando de usar los mismos tipos en List.tsx

El problema en App.tsx en <List people={people}/> en people que obtengo

Type '{ people: IState[]; }' is not assignable to type 'IntrinsicAttributes & IProps[]'.
  Property 'people' does not exist on type 'IntrinsicAttributes & IProps[]'

¿Cómo paso los datos en la prop con tipos?

Respuesta #1

Eso es porque props es el objeto de nivel superior que contiene todas las propiedades pasadas al componente, por lo que deberías desestructurarlo o cambiar la interfaz:

Solución rápida: desestructurar props

const List = ({ people }: { people: IProps[] }) => { ... }

Mejor solución: Cambia el tipo de IProps para que defina la clave anidada people

interface IProps{
    people: Array<{
        name: string;
        age: number;
    }>
}

const List = ({ people }: IProps) => { ... }

Sugerencia

Un consejo adicional: en lugar de declarar la misma interfaz de prop en dos archivos, lo que significa que necesitas actualizarlos en múltiples lugares si cambias de opinión más tarde, siempre puedes hacer que List exporte la prop people (o en realidad, la versión atomizada, digamos IPerson) y luego dejar que el componente padre que lo consume la importe. Un ejemplo:

// List.tsx
export interface IPerson {
    name: string;
    age: number;
}
interface IProps {
    people: IPerson[];
}
const List = ({ people }: IProps) => { ... }

Entonces...

// App.tsx
import List, { IPerson } from './components/List';
const [people, setpeople] = useState<IPerson[]>([ ... ]);

Respuesta #2

Puedes exportar tu interfaz en el primer archivo, y luego importarla en el segundo archivo

export interface IState{
  name: string
  age: number
}

Y luego usar la misma interfaz en List.tsx.

import { IState} from './List';