Definitelytyped: [@ рдкреНрд░рдХрд╛рд░/рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛] рдЧрддрд┐рд╢реАрд▓ рдХреБрдВрдЬреА рдирд╛рдо рдкреНрд░рдХрд╛рд░-рд╕реБрд░рдХреНрд╖рд┐рдд рдХреЗ рд╕рд╛рде рд╕реЗрдЯрд╕реНрдЯреЗрдЯ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛

рдХреЛ рдирд┐рд░реНрдорд┐рдд 18 рдЬреВрди 2018  ┬╖  12рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: DefinitelyTyped/DefinitelyTyped

рдпрджрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдХреИрд╕реЗ рдареАрдХ рдХрд┐рдпрд╛ рдЬрд╛рдП, рддреЛ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдПрдХ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рдХрд░реЗрдВред

  • [x] рдореИрдВрдиреЗ @types/react рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдФрд░ рдореБрдЭреЗ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реБрдИрдВред
  • [x] рдореИрдВрдиреЗ tsc рдХреЗ рдирд╡реАрдирддрдо рд╕реНрдерд┐рд░ рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ред https://www.npmjs.com/package/typescript
  • [x] рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдкреНрд░рд╢реНрди рд╣реИ рдЬреЛ StackOverflow рдХреЗ рд▓рд┐рдП рдЕрдиреБрдкрдпреБрдХреНрдд рд╣реИред (рдХреГрдкрдпрд╛ рд╡рд╣рд╛рдВ рдХреЛрдИ рдЙрдкрдпреБрдХреНрдд рдкреНрд░рд╢реНрди рдкреВрдЫреЗрдВ)ред
  • [x] [рдЙрд▓реНрд▓реЗрдЦ] (https://github.com/blog/821-mention-somebody-the-re-notified) рд▓реЗрдЦрдХ (рджреЗрдЦреЗрдВ Definitions by: рдореЗрдВ index.d.ts ) рддрд╛рдХрд┐ рд╡реЗ рдХрд░ рд╕рдХреЗрдВ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛.

    • рд▓реЗрдЦрдХ: @johnnyreilly , @bbenezech , @pzavolinsky , @digiguru , @ericanderson , @morcerf , @tkrotoff , @DovydasNvickas , @onigoetz , @ theruther4d , @guilhermehubner , @ferdaber , @oajrakoto

рдпрджрд┐ рдЖрдк рд▓реЗрдЦрдХреЛрдВ рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдирдЬрд░рдЕрдВрджрд╛рдЬ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рдореИрдВ 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 рдореЗрдВ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдЬрдм рдЗрд╕реЗ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:

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

рдпрд╣ рдЕрднреА рднреА рдЙрдЪрд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рддреНрд░реБрдЯрд┐ рджреЗрдЧрд╛ рдпрджрд┐ рдорд╛рди рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдВрдкрддреНрддрд┐ рдореВрд▓реНрдп рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕реЗрдЯ рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдпрджрд┐ рдХреБрдВрдЬрд┐рдпрд╛рдВ рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдВрдкрддреНрддрд┐ рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рд╕реЗрдЯ рдХреЗ рднреАрддрд░ рдирд╣реАрдВ рд╣реИрдВ рддреЛ рдЖрдкрдХреЛ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рджреЗрдЧреАред

рд╕рднреА 12 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдпрд╣ рд╕рдВрдХрд▓рдХ рдХреА рд╣реА рдПрдХ рд╕реАрдорд╛ рд╣реИ, рдЧрдгрдирд╛ рдХреА рдЧрдИ рд╕рдВрдкрддреНрддрд┐ рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЕрдиреБрдорд╛рдирд┐рдд рдкреНрд░рдХрд╛рд░ рд╕рдВрдШ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рдпрд╣ рдХреЗрд╡рд▓ 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'))
  }
}

рдореБрдЭреЗ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд░реЗрдкреЛ рдореЗрдВ рдЗрд╕ рд╕реАрдорд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рдорд┐рд▓реА рд╣реИ .. рдХрд┐рд╕реА рднреА рдореМрдХреЗ рдкрд░ рдЖрдкрдХреЛ рдкрддрд╛ рд╣реИ рдХрд┐ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд░реЗрдкреЛ рдореЗрдВ рдЗрд╕ рдкрд░ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ рд╣реИ (рдФрд░ рдХрд╣рд╛рдВ)? рдореВрд▓ рд░реВрдк рд╕реЗ рд╕реЛрдЪ рд░рд╣рд╛ рдерд╛ рдХрд┐ рднрд╡рд┐рд╖реНрдп рдХреЗ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ рдЗрд╕реЗ рд╕рдВрдмреЛрдзрд┐рдд рдХрд░рдиреЗ рдХреА рдХреБрдЫ рдпреЛрдЬрдирд╛рдПрдВ рд╣реИрдВ рдпрд╛ рдирд╣реАрдВред
рдзрдиреНрдпрд╡рд╛рдж!

рдпрд╣рд╛рдВ рдЪрд░реНрдЪрд╛ рд╣реИ, рдЯреАрдПрд╕ рдЯреАрдо рд╕реЗ рдбрд┐рдЬрд╛рдЗрди рдиреЛрдЯреНрд╕, рдФрд░ рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ (рдЬреЛ рдореБрдЭреЗ рд╡рд┐рд╢реНрд╡рд╛рд╕ рд╣реИ рдХрд┐ рднрд╡рд┐рд╖реНрдп рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рд╡рд╛рдкрд╕ рд▓реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛):
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
рдЬрд┐рд╕рд╕реЗ рдХрдИ рдЗрдирдкреБрдЯ рд╡рд╛рд▓реЗ рдлреЙрд░реНрдо рд╕реЗ рдирд┐рдкрдЯрдирд╛ рдЖрд╕рд╛рди рд╣реЛ рдЬрд╛рдПрдЧрд╛ред рдореБрдЭреЗ рдЕрднреА рднреА рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рдкрдбрд╝ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ "рдирд╛рдо" рд╡рд┐рд╢реЗрд╖рддрд╛ рд╡рд╣реА рд╣реИ рдЬреЛ рд╣рдо рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрд╕рдХреЗ рдмрд╛рдж рдЯрд╛рдЗрдк-рд╕реБрд░рдХреНрд╖рд╛ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдореБрдЭреЗ @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 рдореВрд▓ рдкреЛрд╕реНрдЯ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдУрдВ рдореЗрдВ рдХреЗрд╡рд▓ рд╣реИ 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 рдХреЛ keyof State рдирд╣реАрдВ рдбрд╛рд▓ рд╕рдХрддрд╛ рд╣реИред

рдмрд╕ рдПрдХ рдФрд░ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ @arinwt рдХреЛ рдЬреЛрдбрд╝рдирд╛ред

рдЯреАрдПрд▓; рдбреАрдЖрд░: рдЕрдВрддрд┐рдо рд╕рдорд╛рдзрд╛рди рддрд▓ рдкрд░

рдХрдВрд╕реЛрд▓ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рд╕рдорд╛рдзрд╛рди:

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} />
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

variousauthors picture variousauthors  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

[рдбреА3] рдореЙрдбреНрдпреВрд▓ 'рдбреА3-рд╕реНрдХреЗрд▓' рдкрд╣рд▓реЗ рд╣реА 'рдЗрдВрдЯрд░рдкреЛрд▓реЗрдЯрдХреВрд▓' рдирд╛рдо рдХреЗ рдПрдХ рд╕рджрд╕реНрдп рдХреЛ рдирд┐рд░реНрдпрд╛рдд рдХрд░ рдЪреБрдХрд╛ рд╣реИред рдЕрд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкреБрдирдГ рдирд┐рд░реНрдпрд╛рдд рдХрд░рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред
matt-senseye picture matt-senseye  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

jamespero picture jamespero  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

Loghorn picture Loghorn  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

ArtemZag picture ArtemZag  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ