1

stripe form

To validate a Stripe checkout form, I'm trying to dynamically store the change events from the form in state. The event contains elementType which is either 'cardNumber', 'cardExpiry', or 'cardCvc'.

I've set up state as follows to store the events:

interface State {
  cardCvcEvent: stripe.elements.ElementChangeResponse | null;
  cardExpiryEvent: stripe.elements.ElementChangeResponse | null;
  cardNumberEvent: stripe.elements.ElementChangeResponse | null;
}

I have the state updates working, but I'm not satisfied. I want to handle this using dynamic key assignment in a one liner. Here's my working update with the desired line commented out:

public handleChange(e: stripe.elements.ElementChangeResponse) {
  // todo: git gud
  // should be able to figure out typescript so this line works:
  // this.setState({[e.elementType + 'Event']: e});

  switch (e.elementType) {
    case 'cardCvc': {
      this.setState({cardCvcEvent: e});
      break;
    }
    case 'cardExpiry': {
      this.setState({cardExpiryEvent: e});
      break;
    }
    case 'cardNumber': {
      this.setState({cardNumberEvent: e});
      break;
    }
  }
}

I found this, which seems to be pointing in the right direction but it still didn't work for my case:

Typing Dynamic Object Keys With TS

Any thoughts on this are appreciated.

Edit: The typescript error output

Argument of type '{ [x: string]: ElementChangeResponse; }' is not assignable to parameter of type 'State | ((prevState: Readonly<State>, props: Readonly<Props>) => State | Pick<State, "cardCvcEvent" | "cardExpiryEvent" | "cardNumberEvent"> | null) | Pick<State, "cardCvcEvent" | ... 1 more ... | "cardNumberEvent"> | null'.
  Type '{ [x: string]: ElementChangeResponse; }' is missing the following properties from type 'Pick<State, "cardCvcEvent" | "cardExpiryEvent" | "cardNumberEvent">': cardCvcEvent, cardExpiryEvent, cardNumberEvent
Frank Egan
  • 146
  • 8
  • Can you post errors or example for you problem? – Oleg Oct 12 '19 at 17:40
  • @Oleg edited and included the typescript error – Frank Egan Oct 12 '19 at 18:09
  • How did you define IState with dynamic keys? – Oleg Oct 12 '19 at 18:12
  • I'm not using dynamic keys as I know for sure there are only 3 inputs, so I declared them statically in state. I'm wondering how I can use the element name returned by the onChange event to dynamically set the state based on which element was changed. – Frank Egan Oct 12 '19 at 18:17
  • Loook at https://stackoverflow.com/questions/42090191/picks-k-type-with-dynamic-computed-keys – Oleg Oct 12 '19 at 18:22

1 Answers1

0

I’d say it’s not possible for typescript to infer that the key you are using will always be a ‘keyof’ the type of your state, as you are concatenating two strings together - that it why it is showing [x: string] in the error message. You could rework elementType so that it’s type is keyof(YourStateTypesName), and then you would not need to do the string concatenation and the compiler would be happy. Or you could just assign your concatenation to a variable and cast it to keyof(YourStateTypesName) and it will also satisfy the compiler.

C Smith
  • 222
  • 1
  • 6