Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 拾取<;S、 K>;使用动态/计算键键入_Reactjs_Generics_Typescript_Components - Fatal编程技术网

Reactjs 拾取<;S、 K>;使用动态/计算键键入

Reactjs 拾取<;S、 K>;使用动态/计算键键入,reactjs,generics,typescript,components,Reactjs,Generics,Typescript,Components,最新的@types/react(v15.0.6)利用了TypeScript 2.1中为setState添加的功能,即Pick。这是一件好事,因为现在打字是正确的,因为在更新之前,打字“不知道”setState正在合并this.state,而不是替换它 此外,使用Pick使得setState功能在允许输入方面非常严格。无法再向组件定义中未定义的状态添加属性(第二个React.component) 但定义动态更新处理程序也比较困难。例如: import * as React from 'react'

最新的
@types/react
v15.0.6
)利用了TypeScript 2.1中为
setState
添加的功能,即
Pick
。这是一件好事,因为现在打字是正确的,因为在更新之前,打字“不知道”
setState
正在合并
this.state
,而不是替换它

此外,使用
Pick
使得
setState
功能在允许输入方面非常严格。无法再向组件定义中未定义的
状态添加属性(第二个
React.component

但定义动态更新处理程序也比较困难。例如:

import * as React from 'react';


interface Person {
  name: string;
  age: number|undefined;
}


export default class PersonComponent extends React.Component<void, Person> {
  constructor(props:any) {
    super(props);

    this.state = { 
      name: '',
      age: undefined
    };
    this.handleUpdate = this.handleUpdate.bind(this);
  }

  handleUpdate (e:React.SyntheticEvent<HTMLInputElement>) {
    const key = e.currentTarget.name as keyof Person;
    const value = e.currentTarget.value;
    this.setState({ [key]: value });
  }

  render() {
    return (
      <form>
        <input type="text" name="name" value={this.state.name} onChange={this.handleUpdate} />
        <input type="text" name="age" value={this.state.age} onChange={this.handleUpdate} />
      </form>
    );
  }
}
即使
键的类型是
“name”|“age”


除了使用一个单独的
updateName
updateAge
函数之外,我找不到解决方案。有人知道如何使用
Pick
和动态键值吗?

因此,在做了更多的研究之后,我可以提供更多关于上述代码中发生了什么的上下文

当您执行类似于
const name='Bob'
的操作时,变量
name
的类型不是字符串。但是,如果将
const
替换为
let
let name='Bob'
),变量
name
的类型将是
string

这个概念被称为“加宽”。基本上,它意味着类型系统试图尽可能明确。因为不能重新分配
const
,TypeScript可以推断出确切的类型。
let
语句可以重新分配。因此,TypeScript将推断
字符串
(在上面的示例中)作为
名称的类型

同样的情况也发生在
const key=e.currentTarget.name as keyof Person
key
将是(联合)类型
“name”|“age”
,这正是我们想要的。但是在表达式
中,这个.setState({[key]:value})
变量
key
被(错误地)加宽为
字符串


tl;dr;似乎TypeScript中有一个bug。我将问题发布到Github repo和TypeScript团队。:)

作为临时解决方法,您可以执行以下操作:

this.setState({ [key as any]: value });

塞巴斯蒂安的回答不再适用于我(尽管在某个阶段确实如此)。我现在执行以下操作,直到它在Typescript core中得到解决(根据Sebastian答案中列出的问题):

handleUpdate(e:React.synthetic事件){
const newState={};
newState[e.currentTarget.name]=e.currentTarget.value;
this.setState(newState);
}

这很蹩脚,但很有效

我想这可能会解决你的问题

type State = {
  name: string,
  age: number | undefined
};

type StateKeys = keyof State;

dynSetState(key: StateKeys, value: string) {
  this.setState({
    [key]: value
  } as Pick<State, keyof State>)
}
类型状态={
名称:string,
年龄:数字|未定义
};
类型StateKeys=状态键;
dynSetState(键:状态键,值:字符串){
这是我的国家({
[键]:值
}作为选择)
}
如果该值不在可能的属性值类型集中,则仍然会相应地给出错误,但如果键不在可能的属性键集中,则不会给出错误


Ref:

谢谢您的精彩解释。此问题是否已解决,或者是否有其他解决方法?
  handleUpdate (e:React.SyntheticEvent<HTMLInputElement>) {
    const newState = {};
    newState[e.currentTarget.name] = e.currentTarget.value;
    this.setState(newState);
  }
type State = {
  name: string,
  age: number | undefined
};

type StateKeys = keyof State;

dynSetState(key: StateKeys, value: string) {
  this.setState({
    [key]: value
  } as Pick<State, keyof State>)
}