【问题标题】:Assign types on setState to React Typescript将 setState 上的类型分配给 React Typescript
【发布时间】:2019-11-17 15:53:26
【问题描述】:

我正在开发使用 TypeScript 和 React 的项目,并且我正在尝试根据分配给状态的接口来限制数据。

我已将 IState interface 类型分配给具有 uiForm 键分配类型 studentForm interface 的状态。但是,当我将错误的结构化数据或在 studentForm 接口中不存在的错误键分配给 uiForm 键时,它会在未验证类型的情况下被分配。

我的代码如下所示:

interface IProps {}

interface studentForm {
    label: string,
    type: string,
    sequen: string
}

interface IState {
    uiForm: Array < studentForm >
}

export default class AddStudent extends React.Component < IProps, IState > {
    state: IState = {
        uiForm: []
    }
    constructor(props: IProps) {
        super(props);
    }
    componentDidMount() {
        fetch('./assets/studentForm.json').then((res) => res.json())
            .then((data) => {
                this.setState({
                    uiForm: data
                })
            })
            .catch(err => {
                console.log(err);
            })
    }
}

我正在尝试用下面的对象分配 uiForm

studentForm.json:

{ 
   "label":"Admission No.",
   "type":"text",
   "sequence":1
}

理想情况下,它不应该被分配,但它正在分配

将类型分配给 state/setState 的正确方法是什么? 谢谢。

【问题讨论】:

  • 下面的答案是否解决了您的问题?

标签: reactjs typescript


【解决方案1】:

setState 不是这里的关键——如果你查看fetch 的类型签名,你会发现它返回一个带有Body 接口的Response 对象,如下所示:

interface Body {
  ...
  json(): Promise<any>;
}

所以data 实际上变成any 类型并且any 可以分配给...任何东西...,这使得this.setState({ uiForm: data }) 正确类型。

如果您需要首先验证fetch 结果,请使用unknown 类型注释data,然后使用type guards(分支逻辑)或assertion functions(断言/不变逻辑; TS 3.7)。断言示例:

export default class AddStudent extends React.Component<IProps, IState> {
    ...
    componentDidMount() {
        fetch('./assets/studentForm.json').then((res) => res.json())
            // type data as unknown
            .then((data: unknown) => {
                // assertion function narrows data type or throws error
                assertStudentFormArray(data)
                // data type narrowed to Array<studentForm> here
                this.setState({
                    uiForm: data
                })
            })
    }
}

function assertStudentFormArray(args: any): asserts args is IState["uiForm"] {
    // do your validation here ...
    if (!Array.isArray(args)) throw new Error("Got no array...")
    if (args.some(arg => !("label" in arg))) throw new Error("Got no studentform...")
}

Playground

【讨论】:

    猜你喜欢
    • 2022-08-23
    • 1970-01-01
    • 1970-01-01
    • 2019-06-07
    • 2022-11-18
    • 2021-10-17
    • 2020-03-26
    • 1970-01-01
    • 2020-11-09
    相关资源
    最近更新 更多