λ¬Έμ λ₯Ό ν΄κ²°νλ λ°©λ²μ μκ³ μλ€λ©΄ λμ ν 리νμ€νΈλ₯Ό νμμμ€.
@types/react
ν¨ν€μ§λ₯Ό μ¬μ©ν΄ 보μλλ° λ¬Έμ κ° μμμ΅λλ€.Definitions by:
in index.d.ts
) λλ΅νλ€.μμ±μλ₯Ό μΈκΈνμ§ μμΌλ©΄ λ¬Έμ κ° λ¬΄μλ©λλ€.
type-safetyκ° μλ κ³μ°λ μμ± μ΄λ¦μμ μμ±λλ κ°μ²΄λ‘ setState
λ₯Ό νΈμΆν μ μμ΅λλ€.
type State = {
username: string,
password: string
};
type StateKeys = keyof State;
class A extends React.Component<{}, State> {
dynSetState(key: StateKeys, value: string) {
this.setState({
[key]: value // Error here. Pretty sure key is in StateKeys
});
}
}
#18365 λ° https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment -351868649 μ ν΄κ²° λ°©λ²μ μκ³ μμ΅λλ€. κ·Έλ¬λ ν΄κ²° λ°©λ²μ μ¬μ©ν λ Typescriptλ λ€μκ³Ό κ°μ κ²½μ° μ€λ₯κ° λ°μνμ§ μμ΅λλ€.
dynLooselySetState(key: string, value: string) {
this.setState(prevState => ({
...prevState,
[key]: value // No error here, but can't ensure that key is in StateKeys
}));
}
μ΄κ²μ μ»΄νμΌλ¬ μ체μ νκ³μ
λλ€. κ³μ°λ μμ± ν€λ₯Ό ν΅ν΄ μ μΆλ μ νμ 곡μ©μ²΄ μ νμ μ§μνμ§ μμΌλ©° string
, number
, symbol
λλ μ΄λ€ μ€ νλμ 리ν°λ΄λ§ μ§μν©λλ€. 3, κ·Έ μ€ νλμ μ‘°ν©μμ κ°μ§νλ©΄ μΌλ° string
μ νμΌλ‘ κ°μ λ³νν©λλ€. μ¬κΈ°μ ν΄κ²° λ°©λ²μ κ°μ²΄λ₯Ό κ°μ λ³ννλ κ²μ
λλ€.
dynSetState(key: StateKeys, value: string) {
this.setState({
[key]: value
} as Pick<State, keyof State>)
}
κ°μ΄ κ°λ₯ν μμ± κ° μ ν μ§ν©μ μμΌλ©΄ μ¬μ ν μ μ νκ² μ€λ₯κ° λ°μνμ§λ§ ν€κ° κ°λ₯ν μμ± ν€ μ§ν©μ μμΌλ©΄ μ€λ₯κ° λ°μνμ§ μμ΅λλ€.
μ νν @ferdaber λ μ΄μ κ°μ IMHO μΊμ€ν μ΄ κ·Έλ€μ§ "μ’μ ν¨ν΄"μ΄ μλμ§λ§ μ λ°μ μΌλ‘ ν΄λμ€ μΈλΆμμ ν΄λΉ μ½λ°±μ ν μ€νΈνκΈ° μ¬μ΄ μμν ν μ€νΈ κΈ°λ₯μΌλ‘ μΆμΆνλ κ²κ³Ό κ°μ λͺ¨λ² μ¬λ‘λ₯Ό λ€μ μ€μνλ μ½λ°± ν¨ν΄μ ν΅ν΄ μνλ₯Ό μ λ°μ΄νΈνλ κ²μ μ νΈν΄μΌ ν©λλ€. :)
μ’μ:
class C extends Component<{}, State> {
updateState(key: StateKeys, value: string) {
this.setState((prevState) => ({
...prevState,
[key]: value,
}));
}
}
λ λμ:
const updateState = <T extends string>(key: keyof State, value: T) => (
prevState: State
): State => ({
...prevState,
[key]: value
})
class C extends Component<{}, State> {
doSomething(){
this.setState(updateState('password','123124'))
}
}
typescript repoμμ μ΄ μ νμ λν κ΄λ ¨ λ¬Έμ λ₯Ό μ°Ύμ§ λͺ»νμ΅λλ€. μ΄κ²μ΄ typescript repoμμ λ
Όμλμλμ§(κ·Έλ¦¬κ³ μ΄λμμ) μ μ μμ΅λκΉ? κΈ°λ³Έμ μΌλ‘ ν₯ν typescript λ²μ μμ μ΄ λ¬Έμ λ₯Ό ν΄κ²°ν κ³νμ΄ μλμ§ κΆκΈν©λλ€.
κ°μ¬ ν΄μ!
λ€μμ ν λ‘ , TS νμ λμμΈ λ
ΈνΈ, μμ μλ(ν₯ν λ²μ μμλ μ² νλ κ²μΌλ‘ μκ°λ¨)μ
λλ€.
https://github.com/Microsoft/TypeScript/issues/13948
https://github.com/Microsoft/TypeScript/issues/18155
https://github.com/Microsoft/TypeScript/pull/21070
μ€μ λ‘ λ΄κ° λ¬μ±νλ €λ κ²μ λ€μκ³Ό κ°μ μμ
μ μννλ κ²μ
λλ€. https://reactjs.org/docs/forms.html#handling -multiple-inputs
κ·Έλ¬λ©΄ μ¬λ¬ μ
λ ₯μ΄ μλ μμμ λ μ½κ² μ²λ¦¬ν μ μμ΅λλ€. "name" μμ±μ΄ μ°λ¦¬κ° κΈ°λνλ κ²κ³Ό κ°μμ§ νμΈν΄μΌ ν μλ μμ§λ§ κ·Έ νμλ μ ν μμ μ±μ΄ μλν΄μΌ ν©λλ€.
@ferdaber μ μ루μ
μ as unknown
λ₯Ό μΆκ°ν΄μΌ νμ΅λλ€.
this.setState({
[key]: value
} as unknown as Pick<State, keyof State>)
key
κ° λΆμΈμ΄λ©΄ κ²½κ³ νμ§λ§ μ«μμ΄λ©΄ κ²½κ³ νμ§ μμ΅λλ€!
κ·Έλμ μ λ μ΄ λ 짧μ μ루μ μ μ ννμ΅λλ€.
this.setState<never>({
[key]: value
})
key
κ° λΆμΈ λλ μ«μμΈ κ²½μ° κ²½κ³ ν©λλ€.
https://github.com/DefinitelyTyped/DefinitelyTyped/issues/26635#issuecomment -400260278μ΄ μλνλ μ΄μ λ 무μμ λκΉ? λ΄ λ§μ ν€κ° μ¬μ ν μ λμ¨ μ νμ΄λΌλ λ»μΈκ°μ?
μ΄κ²μ΄ λΉμ μ λμΈ κ²μ λλ€
type IAction = {
[P in keyof IAppSettings]?: IAppSettings[P];
};
function reducer(state: IAppSettings, action: IAction) {
return {
...state,
...action,
};
}
μ΄ λ¬Έμ μ μ§μ μ΄ μμ΅λκΉ?
λλ μ΄κ²μ μλμν¬ μ μμλ€
handleTextChange(name: keyof State, value: any) {
this.setState({
...this.state,
[name]: value
});
}
μ΄κ²μ λ³΄κ³ μμ μ μν μ νμ μ μ©νλ €λ λ€λ₯Έ μ¬λλ€μ μν΄ μλ³Έ κ²μλ¬Ό λ° μλ΅μ value
μ νμ State
λͺ¨λ μμ± μ ν λλ¬Έμ string
μ State
λ string
μ
λλ€. λ€λ₯Έ μ νμ΄ ν¬ν¨λ λ any
λλ μΆκ° μΊμ€ν
μ μ¬μ©νλ κ²μ νΌνκ³ λμ value
μ νμ΄ ν€ μ νκ³Ό μΌμΉνλ μ νμ ν΄λΉνλλ‘ μ νμ μ ννλ κ²μ΄ μ’μ΅λλ€.
interface State {
name: string;
age: number;
}
type StateKeys = keyof State;
function dynSetState<K extends StateKeys>(key: K, value: State[K]) {
this.setState({ [key]: value }); // fails; if only this worked...
this.setState({ [key]: value } as Pick<State, K>); // clean cast works
this.setState((s, _) => ({ ...s, [key]: value })); // avoids cast, but changes js
}
dynSetState("name", "a"); // works as expected
dynSetState("name", 1); // fails as expected
dynSetState("age", "a"); // fails as expected
dynSetState("age", 1); // works as expected
#26635(λκΈ)μ΄ μλνλ μ΄μ λ 무μμ λκΉ? λ΄ λ§μ ν€κ° μ¬μ ν μ λμ¨ μ νμ΄λΌλ λ»μΈκ°μ?
μ μ’
λ₯ λλ¬Έμ μλ { ...prevState }
μΆ©λΆν μΌμΉ State
μ°λ¦¬κ° κ΅κ°μ μ΅μν λͺ¨λ μμ±μ΄ κΈ°λ³Έμ μΌλ‘ μκΈ° λλ¬Έμ. κ·Έκ² μμ΄λ _μλνμ§ μλ_ μ΄μ λ₯Ό μ΄ν΄νλ λ° λμμ΄ λ μ μμ΅λλ€. λ¬Έμ μ κ·Όλ³Έ μμΈμ μμ±λ κ°μ²΄μ μ νμ
λλ€. { [key: K]: State[K] }
κ° μΆ©λΆν ꡬ체μ μ΄μ§ μμ΅λλ€. κ·Έκ²μμ΄λ€ { [x: string]: State[K] }
ν€ μΊμ€ν
ν μμλ string
Aλ₯Ό keyof State
.
λ€λ₯Έ μλ‘ @arinwtμ μΆκ°νκΈ°λ§ νλ©΄ λ©λλ€.
TL;DR: νλ¨μ μ΅μ’ μ루μ
μ½μ μ€λ₯κ° μλ νμ₯λ μ루μ :
type RegisterTypes = {
email: string;
password: string;
}
// ...
const [state, setState] = useState<RegisterTypes>({
email: "",
password: "",
});
// ...
const onChangeInput = (key: keyof RegisterTypes) => (event: React.ChangeEvent<HTMLInputElement>) => {
setState({
[key]: event.target.value
} as Pick<RegisterTypes, typeof key>);
};
// ...
<input type="email" onChange={onChangeInput('email')} value={state.email} />
μ΄κ²μ μ½μμμ λ€μκ³Ό κ°μ μ€λ₯λ₯Ό μ 곡νμ§λ§:
Warning: A component is changing a controlled input of type password to be uncontrolled. Input elements should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
μ½μ μ€λ₯κ° μλ λ체 μ루μ (μμμ):
κ²½κ³ λ ν΄μ€λ€.
type RegisterTypes = {
[key: string]: string;
}
// ...
const onChangeInput = (key: string) => (event: React.ChangeEvent<HTMLInputElement>) => {
setState({
[key]: event.target.value
});
};
μ΅μ’ μ루μ μ€λ₯ μμ:
type RegisterTypes = {
email: string;
password: string;
}
// ...
const onChangeInput = (event: React.ChangeEvent<HTMLInputElement>) => {
const newState = { ...state };
newState[event.target.name as keyof RegisterTypes] = event.target.value;
setState(newState);
};
// ...
<input name="email" type="email" onChange={onChangeInput} value={state.email} />
κ°μ₯ μ μ©ν λκΈ
μ΄κ²μ μ»΄νμΌλ¬ μ체μ νκ³μ λλ€. κ³μ°λ μμ± ν€λ₯Ό ν΅ν΄ μ μΆλ μ νμ 곡μ©μ²΄ μ νμ μ§μνμ§ μμΌλ©°
string
,number
,symbol
λλ μ΄λ€ μ€ νλμ 리ν°λ΄λ§ μ§μν©λλ€. 3, κ·Έ μ€ νλμ μ‘°ν©μμ κ°μ§νλ©΄ μΌλ°string
μ νμΌλ‘ κ°μ λ³νν©λλ€. μ¬κΈ°μ ν΄κ²° λ°©λ²μ κ°μ²΄λ₯Ό κ°μ λ³ννλ κ²μ λλ€.κ°μ΄ κ°λ₯ν μμ± κ° μ ν μ§ν©μ μμΌλ©΄ μ¬μ ν μ μ νκ² μ€λ₯κ° λ°μνμ§λ§ ν€κ° κ°λ₯ν μμ± ν€ μ§ν©μ μμΌλ©΄ μ€λ₯κ° λ°μνμ§ μμ΅λλ€.