簡體   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