2017-02-07 9 views
6

最新の@types/reactv15.0.6)は、setStateのタイプスクリプト2.1で追加された機能、つまりPick<S, K>を使用します。更新タイピングが "知らなかった"前にsetStateがそれを置き換えるのではなくthis.stateにマージしているので、これは良いことです。ピック<S, K>ダイナミック/計算キー付きタイプ

また、Pickを使用すると、setStateは許可入力の点で非常に厳しいものになります。 。React.Componentの第二の汎用コンポーネント定義(で定義されていないstateにプロパティを追加することはもはや

可能ではありません。しかし、動的更新ハンドラを定義することも困難です。たとえば:。

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機能は、次のエラー

keyのタイプは "name" | "age"であっても
[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; }'. 

をスローします。

別のupdateNameupdateAge機能を持っている以外は、解決策が見つかりません。誰も動的なキー値でPickを使用する方法を知っていますか?

答えて

5

私は上記のコードで何が起こっているのかについてもう少し詳しく説明します。あなたがconst name = 'Bob'ような何かを行うと

は、変数nameのタイプは'Bob'ない文字列です。ただし、constletlet name = 'Bob')に置き換えた場合、変数namestringとなります。

この概念は「拡大」と呼ばれます。基本的には、型システムは可能な限り明示的にしようとします。 constは再割り当てできないため、TypeScriptは正確な型を推論できます。 letステートメントを再割り当てすることができます。したがって、TypeScriptは、のタイプとしてstring(上記の例では)を推論します。

const key = e.currentTarget.name as keyof Personでも同じことが起こります。 keyは、(ユニオン)タイプ"name"|"age"になります。これはまさに私たちが望むものです。 this.setState({ [key]: value });変数keyは、stringに(誤って)拡大されています。


tl; dr; TypeScriptにバグがあるようです。 GithubのレポとTypeScriptチームis investigating the problemに問題を投稿しました。

this.setState({ [key as any]: value }); 
:あなたが行うことができます一時的な回避策として:)

関連する問題