【问题标题】:Type '{}' is not assignable to type '() =>类型 '{}' 不可分配给类型 '() =>
【发布时间】:2020-04-02 21:29:45
【问题描述】:

我有一个 TypeScript 问题要问你。我想知道您如何在 useState 中使用 id、标题、带有接口的文本等传入属性“指定”单个对象。

见下面的代码:

import React, { useState, useEffect } from "react";

interface SinglePostProps {
  match: any;
}

interface SinglePostState {
  id: number;
  heading: string;
  text: string;
}

const Post: React.FC<SinglePostProps> = ({ match }) => {
  useEffect(() => {
    fetchSinglePost();
  }, []);

  const [singlePost, setSinglePost] = useState<SinglePostState>({});

  const fetchSinglePost = async () => {
    try {
      const fetchSinglePost = await fetch(
        `http://localhost:3001/api/posts/${match.params.id}`
      );
      const singlePost = await fetchSinglePost.json();
      console.log("Single Post", singlePost);
      setSinglePost(singlePost);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <>{/* <h1>{singlePost.heading}</h1>
      <p>{singlePost.text}</p> */}</>
  );
};

export default Post;

我现在得到的错误是:

如果我控制台记录保存为 singlePost 状态的对象,我会收到以下消息:

据我了解,您想指定您是否期望一个数组或一个对象进入状态。因此,当我这样做时,我的 PostList 组件会在数组中呈现对象列表,我执行了以下操作,但它没有抱怨:

const [items, setItems] = useState<PostListState[]>([]);

我对 TypeScript 很陌生,所以如果有人能解释我如何处理这些 TypeScript 错误消息,我将不胜感激? :)

先谢谢了, 埃里克

【问题讨论】:

  • 看起来它希望您提供一个具有在SinglePostState 接口中定义的所有属性的对象,因为它们不是optional
  • 嗯,也许吧。因此,如果我将属性设置为可选,它不会抱怨(显然),但你能告诉我为什么会这样吗?我应该怎么想?可选属性可以是未定义的吗?我是否总是必须在 useState 中将它们写成一个对象?
  • 在您的情况下,您可能希望将状态对象设为可选,而不是属性。因此,在获取帖子时,您拥有null 而不是{},并且可以通过这种方式检查帖子是否准备就绪。我不使用 TS 但它可能接近/* ... */ = useState&lt;SinglePostState | null&gt;(null)

标签: javascript reactjs typescript react-hooks


【解决方案1】:

您是在告诉编译器每个 PostListState 对象 必须 有它们的参数,如果你想拥有只需要添加的可选参数?在钥匙之后。

http://www.typescriptlang.org/docs/handbook/advanced-types.html#optional-parameters-and-properties


interface SinglePostStateOPTIONAL {
  id?: number;
  heading?: string;
  text?: string;
}


interface SinglePostState {
  id: number;
  heading: string;
  text: string;
}

//useState<SinglePostState>(/* only works with {id:0, heading:'', text:''}*/);
//useState<SinglePostStateOPTIONAL>(/* works with both {} or {id:0, heading:'', text:''}*/);

//This will fail
const [items, setItems] = useState<PostListState>({});

//This will be right 
const [items, setItems] = useState<PostListState>({id: 0, heading:'', text:''});

//This also will be right

const [items, setItems] = useState<PostListStateOPTIONAL>({});



当您使用数组时,您可以执行以下操作:


const [items, setItems] = useState<PostListState[]>([]);

你对 PostListState 对象数组没有任何问题,因为数组的长度等于 0,这意味着你可以有一个空的 PostListState 数组。

//You can have this
const [items, setItems] = useState<PostListState[]>([]); 

// This will fail
const [items, setItems] = useState<PostListState[]>([{}]); 

// This will be right
const [items, setItems] = useState<PostListState[]>([{id: 0, heading:'', text:''}]); 

// This will fail too because you need to pass all the params of the object.
const [items, setItems] = useState<PostListState[]>([{id: 0, heading:''}]); 

【讨论】:

    【解决方案2】:

    正如错误所说,setState 函数接受一个遵循 SinglePostState 接口的对象或一个返回此类对象的函数。您在发送不符合 SinglePostState 接口的空对象文字时看到错误,而在第二种情况下,空数组也是 PostListState 元素的有效数组。您可以发送一个空数组或一个数组,其中每个元素都遵循 PostListState 接口。仅当尝试发送具有其他元素类型(例如数字数组或完全不同的数据类型)的数组时才会失败。

    【讨论】:

    • 这提供了对错误的准确描述,但没有提供任何解决方案。
    • 我认为解决方案很简单,您可以实例化一个 SinglePostState 类型的空对象,然后将该对象传递给 setState 函数,或者您可以传递任何通用参数 useState({});
    猜你喜欢
    • 2019-06-02
    • 2018-01-04
    • 2020-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-26
    • 2023-01-28
    相关资源
    最近更新 更多