![](/img/trans.png)
[英]Why does the new `Pick<T, K extends keyof T>` type allow subsets of `K` in React's `setState()`?
[英]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"
。
除了具有單獨的updateName
和updateAge
函數之外,我找不到解決方案。 有誰知道如何將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.