React/Typscript: typehint any 不起作用

React/Typscript: typehint any doesn't work

我有一个非常简单的反应组件,名为: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[]'.

我得到上述错误 4 次,for user.login, user.public_repos, user.followers, user.avatar_url

"Typehint" in React.Component<{any, any}> 与状态类型无关,这是您指定的道具类型。查看 React 组件的声明:declare class React$Component<Props, State = void> { ...

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

interface IState {}

interface IProps {}

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

当你这样做时:

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

您只是将组件道具类型定义为一个对象,该对象具有两个都称为 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,
    });
  }
  ...
}

你犯了语义错误。虽然您的程序在语法上是有效的,但这并不意味着您的意图。

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

<name> [: type]

也就是说,名称首先出现并且是必需的,并且始终是必需的,并且如果需要,可以在其后跟一个类型注释。

因此,如果我写,

type Props = {
    any
};

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

type Props = {
    any: any
};

因为我没有类型注释,也没有推断它的上下文。

此外,我写,

type Props = {
    any,
    any
};

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

您可能打算像这样为 PropsState 类型参数指定类型 any

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

}

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

有多种原因:

  1. React.Component 接口接受两种类型,React.Component<P, S> 其中 P 是 props 的类型,S 是状态的类型。它还可以接受一个类型,它只是 P。这就是你的情况,你将类型 P 定义为对象 {any, any} (打字稿应该抱怨它,因为你指定了重复的键)。这意味着您根本没有为国家提供类型。其中来自 DefinetelyTyped should be any

  2. 您在 class 上明确定义了 state,因此打字稿从定义中推迟了它的类型。 state.user是一个数组,所以这个元素上没有avatar_url

要解决此问题,您可以尝试在定义

时明确说明 state 是任意的
    state: any = {
        user: []
    }

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

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

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