繁体   English   中英

挑选<s, k>使用动态/计算键键入</s,>

[英]Pick<S, K> type with dynamic/computed keys

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

此外,使用Pick使setState函数在允许的输入方面非常严格。 不再可能向组件定义中未定义的state添加属性( 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>
    );
  }
}

setState函数会抛出如下错误

[ts] Argument of type '{ [x: string]: string; }' is not assignable 
     to parameter of type 'Pick<Person, "name" | "age">'.
       Property 'name' is missing in type '{ [x: string]: string; }'.

即使key的类型是"name" | "age" "name" | "age"

除了具有单独的updateNameupdateAge函数之外,我找不到解决方案。 有谁知道如何将Pick与动态键值一起使用?

因此,在进行更多研究之后,我可以提供更多有关上述代码中发生的情况的上下文。

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

这个概念叫做“拓宽”。 基本上,这意味着类型系统试图尽可能明确。 因为const不能被重新赋值,TypeScript 可以推断出确切的类型。 let语句可以重新赋值。 因此,TypeScript 会将string (在上面的示例中)推断为name的类型。

const key = e.currentTarget.name as keyof Person也会发生同样的情况。 key将是(联合)类型"name"|"age" ,这正是我们想要的。 但是在表达式中this.setState({ [key]: value }); 变量key被(错误地)扩展为string


TL;博士; TypeScript 中似乎存在错误。 我将问题发布到 Github 存储库,TypeScript 团队正在调查该问题 :)

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

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

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

  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>)
}

如果该值不在可能的属性值类型集中,这仍然会适当地给出错误,但如果键不在可能的属性键集中,则不会给您错误。

参考:https ://github.com/DefinitelyTyped/DefinitelyTyped/issues/26635

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM