React / Typscript:键入提示不起作用

时间:2019-10-21 14:07:55

标签: reactjs typescript jsx typescript-generics

我有一个非常简单的react组件,名为:github.tsx

其中有以下代码:

import React from 'react'
import axios from 'axios'

class Github extends React.Component<{any, any}>{

  state = {
    user: []
  }

  getRepoUser = async () => {
    let res = await axios.get('https://api.github.com/users/example');
    this.setState({
      user: res.data
    })
  }

  componentDidMount () {
   this.getRepoUser()
  }

  render () {
    const { user } = this.state

    return (
      <div>
        <h2>{user.login}</h2>
        <p> repos: {user.public_repos} </p>
        <p>followers: {user.followers}</p>
        <img src={user.avatar_url} alt=""/>
      </div>
    )
  }
}

export default Github

我认为通过向组件中添加<{any, any}>,我不会有任何问题,但是会看到类似以下的控制台错误:

backend.js:6 /home/example/tuts/components/github.tsx
./components/github.tsx
[tsl] ERROR in /home/example/tuts/components/github.tsx(35,24)
      TS2339: Property 'avatar_url' does not exist on type 'any[]'.

对于user.loginuser.public_reposuser.followersuser.avatar_url,我收到4次以上错误

4 个答案:

答案 0 :(得分:1)

创建组件时,传递给React.Component的第一种类型是props类型,而第二种定义状态类型:

interface IState {}

interface IProps {}

class Component extends React.Component<IProps, IState> {

执行此操作时:

class Github extends React.Component<{any, any}>

您仅将组件props类型定义为具有两个都称为any的属性的对象,这将不起作用。

您的组件键入应改为:

class Github extends React.Component<any, any>

state.user的推断类型也是一个数组,因为初始状态是:

state = {
  user: []
}

这就是为什么您会收到有关user.loginuser.public_repos ...

的错误的原因

您可以这样输入状态:

interface IState {
  user: User;
}

interface User {
  login: string;
  public_repos: string;
  followers: string;
  avatar_url: string;
}

class Github extends React.Component<any, IState> {
  public state = {
    user: {
      login: "",
      public_repos: "",
      followers: "",
      avatar_url: "",
    },
  };

  public getRepoUser = async () => {
    const res = await axios.get<User>("https://api.github.com/users/example");
    this.setState({
      user: res.data,
    });
  }
  ...
}

答案 1 :(得分:1)

您正在犯语义错误。尽管您的程序在语法上是有效的,但这并不意味着您打算执行什么。

关键点在于,在TypeScript中,声明的形式为

<name> [: type]

也就是说,名字是第一位的,并且总是必需的,如果需要,可以在其后加上类型注释。

因此,如果我写信,

type Props = {
    any
};

我正在声明一个名为any属性类型。以上等同于

type Props = {
    any: any
};

因为我没有类型注释,也没有上下文可以推断出来。

此外,我写道,

type Props = {
    any,
    any
};

我两次声明了一个名为any的成员,这是一个错误。

您可能希望为anyProps类型的参数都指定类型State

class Github extends React.Component<any, any> {

}

但是您改为为{any, any}指定类型Props,而没有为State指定类型。

答案 2 :(得分:1)

有多种原因:

  1. React.Component接口接受两种类型,React.Component<P, S>,其中P是道具的类型,S是状态的类型。它也可以接受单个类型,即P。这就是您所遇到的情况,您正在将类型P定义为对象{any, any}(打字稿应该抱怨它,因为您指定了重复键)。这意味着您根本不提供国家的类型。来自DefinetelyTyped should be any

  2. 您是在类上显式定义state,因此打字稿会从定义中推迟其类型。 state.user是一个数组,因此该元素上没有avatar_url

要解决此问题,您可以尝试明确声明state在定义时为

    state: any = {
        user: []
    }

更好的解决方案是实际为状态定义类型或接口,而不使用任何状态。应该避免使用any,尤其是在为应用程序编写的代码中。

您可以定义用户喜欢的类型或界面:

type User = {
    name: string,
    avatar?: string
}
// or 
interface IUser {
    name: string,
    avatar?: string
}

答案 3 :(得分:0)

React.Component<{any, any}>中的

“ Typehint”与状态类型无关,这是您指定的道具类型。检出react组件的声明:declare class React$Component<Props, State = void> { ...