Typescript 通用状态更改函数类型转换错误 [英] Typescript generic state change function type casting error

查看:67
本文介绍了Typescript 通用状态更改函数类型转换错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个通用函数来更改状态.

I'm creating a generic function to change the state.

错误信息:

TS2345: Argument of type '() => { [x:string]: string }' is not assignable to parameter of type 'IUserSignUpState | Pick<IUserSignUpState, "url" | "errors"> | ((prevState: Readonly<IUserSignUpState>, props: Readonly<IUserSignUpState>) => IUserSignUpState | Pick<...> | null) null'.

Type '() => { [x: string] string; }' is not assignable to type '(prevState: Readonly<IUserSignUpState>, props: Readonly<IUserSignUpState>) => IUserSignupState | Pick<IUserSignUpState>, "url" | "errors" | null'. 

Type '{ [x: string]: string; }' is not assignable to type 'IUserSignUpState | Pick<IUserSignUpState, "url" | "errors"> | null'.

Type '{ [x: string]: string; }' is missing the following properties from type 'Pick<IUserSignUpState, "url" | "errors">': url, errors.

这是通用更改函数的示例:

This is the example of the generic change function:

./UserSignUp.tsx


interface IUserSignUpState {
  url: string;
  errors: string[];
  // following can be used, but will lose type checking (*)
  // [key: string]: string;
}

class UserSignUp extends React.Component<{}, IUserSignUpState>
  state = {
    url: '',
    name: '',
    errors: [],
  };

  render() {
    const { url, errors } = this.state;
    return (
      <form>
        <input type="text" name="url" value={url} onChange={this.change} />
        <input type="text" name="name" value={name} onChange={this.change} />
      <form>
    )
  }

  change = (event:React.ChangeEvent<HTMLInputElement>) => {
    const name = event.target.name;
    const value = event.target.value;

    // gives error here:
    this.setState(() => {
      return {
        [name]: value
      }
    })
  }
};

在这个例子中,change 事件应该只允许更新 url: string;name: string;,而不是 errors: [].

In this example the change event should only be allowed to update url: string; and name: string;, and not errors: [].

我应该定义 'url' 和 'name' 类型并以某种方式在 change 函数中重用它们吗?

Should I be defining the 'url' and 'name' types and reuse that in the change function somehow?

*在 Typescript 文档中,它指出 可索引类型 可以使用.但是,这样做我将失去类型检查.一个副作用是我还可能设置错误"状态,这通常不应该从更改函数中实现.

*In the Typescript documentation it states that Indexable types can be used. However, by doing so I will lose type checking. And a side-effect is that I could potentially also set the 'error' state, which typically shouldn't be possible from the change function.

更新:基于此Stackoverflow 问题,以下解决方案是可能的:

update: based on the answer in this Stackoverflow Question, the following solution is possible:

拆分界面:

interface IInputState {
  url: string;
}

interface IUserSignUpState extends IInputState {
  errors: string[];
}

并通过以下任一方式重新使用该界面:

And re-use that interface, by either:

this.setState({ [name]: value } as Partial<IInputStates>)

或:

const name = event.target.name as keyof IInputStates;
const value = event.target.value;

this.setState(():IInputStates => {
  return { [name]: value }
});

推荐答案

使用类型不会阻止错误属性被更改,因为类型检查仅在编译时适用.当它到达浏览器时,它仍将作为普通的旧动态 JavaScript 运行.

Using types won't prevent the errors property from being changed as the type checking applies at compile time only. This will still run as plain old dynamic JavaScript when it gets to the browser where anything goes.

如果您想限制更改功能所作用的属性,您需要检查属性名称,例如针对一组允许的值.

If you want to restrict the properties the change function acts on you need to check the property name e.g. against an array of allowed values.

作为旁注,您的输入缺少 name 属性.

As a side note your inputs are missing the name property.

 render() {
    const { url, errors } = this.state;
    return (
      <form>
        <input type="text" name="url" value={url} onChange={this.change} />
        <input type="text" name="name" value={name} onChange={this.change} />
      <form>
    )
  }

  change = (event:React.ChangeEvent<HTMLInputElement>) => {
    const name = event.target.name;
    const value = event.target.value;

    if (!isValidProperty(name)) return;

    this.setState({ [name]: value } as Partial<IInputStates>)
  }

  // Dummy instance to force a compile warning and ensure we capture all the property names
  const inputExample: IInputStates = { url: '' };
  const inputKeys = Object.keys(inputExample);

  function isValidProperty(name: string): name is keyof IInputStates {
    return inputKeys.includes(name);
  }

这篇关于Typescript 通用状态更改函数类型转换错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆