Home > Net >  React and typescript, Binding element 'todos' implicitly has an 'any' type."
React and typescript, Binding element 'todos' implicitly has an 'any' type."

Time:12-30

typescript complains the prop { todos }, it says "Binding element 'todos' implicitly has an 'any' type."

Anyone could help me? I tried so many way still couldn't solve it.. Do I need to also pass the interface to the child?

//TodoList.tsx
import React from "react";

export default function TodoList({ todos }) {
  return <div>{todos.id}</div>;
}

//App.tsx
import { useState, useRef } from "react";
import { uuid } from "uuidv4";
import TodoList from "./TodoList";

export default function App() {
  interface Todo {
    id: string;
    title: string | undefined;
    completed: boolean;
  }

  const [todos, setTodos] = useState<Todo[]>([]);
  const refTitle = useRef<HTMLInputElement | null>(null);

  const handleAdd = () => {
    const title = refTitle.current?.value;
    setTodos((todos) => {
      return [...todos, { id: uuid(), title: title, completed: false }];
    });
  };

  return (
    <>
      <TodoList todos={todos} />
      <input ref={refTitle} type="text" />
      <button onClick={handleAdd}>Add</button>
    </>
  );
}

CodePudding user response:

You should pass the todos as props of the Todo type array.

App.tsx

import { useState, useRef } from "react";
import uuid from "react-uuid";
import TodoList from "./TodoList";
import { Todo } from "./types";

export default function App() {
  const [todos, setTodos] = useState<Todo[]>([]);
  const refTitle = useRef<HTMLInputElement | null>(null);

  const handleAdd = () => {
    const title = refTitle.current?.value;
    setTodos((prev) => [
      ...prev,
      { id: uuid(), title: title, completed: false }
    ]);
  };

  return (
    <>
      <TodoList todos={todos} />
      <input ref={refTitle} type="text" />
      <button onClick={handleAdd}>Add</button>
    </>
  );
}

TodoList.tsx

import { Todo } from "./types";

export default function TodoList({ todos }: { todos: Todo[] }) {
  return (
    <>
      {todos.map((todo, i) => (
        <div key={i}>{todo.title}</div>
      ))}
    </>
  );
}

types.ts

export interface Todo {
  id: string;
  title: string | undefined;
  completed: boolean;
}

This is a result of React components only taking objects as arguments

Here's the working solution https://codesandbox.io/s/props-to-child-tsx-vuzo2s

CodePudding user response:

You have not defined the type of prop that you are passing onto the Todolist. Just add your interface from app.tsx to todolist.tsx and there pass the type Todo to props.I have edited the same in the code snippets below.

import React from "react";
import {Todo} from "./App"

export default function TodoList({ todos : Todo }) {
  return <div>{todos.id}</div>;
}

import { useState, useRef } from "react";
import { uuid } from "uuidv4";
import TodoList from "./TodoList";

export interface Todo {
    id: string;
    title: string | undefined;
    completed: boolean;
  }


export default function App() {
  
  const [todos, setTodos] = useState<Todo[]>([]);
  const refTitle = useRef<HTMLInputElement | null>(null);

  const handleAdd = () => {
    const title = refTitle.current?.value;
    setTodos((todos) => {
      return [...todos, { id: uuid(), title: title, completed: false }];
    });
  };

  return (
    <>
      <TodoList todos={todos} />
      <input ref={refTitle} type="text" />
      <button onClick={handleAdd}>Add</button>
    </>
  );
}

  • Related