

react-stripe-js
自体はTypeScriptに対応しているというのをドキュメントで見たのですが、どのようにインストールした型を当てていけば良いか分からないです。
`CardElementComponent` とimportとして使用するみたいな記事をみて `const handleChange = async
(event: CardElementComponent) => {` のようにして見たのですが
関数内で赤の波線が出て型が当たってないと出るのでおそらく上手く行ってないです。  
詳しい方教えて頂けないでしょうか?  
よろしくお願いします。

[code]

    import React, { useState, useEffect } from "react";
    import {
      CardElement,
      CardElementComponent,
      useStripe,
      useElements
    } from "@stripe/react-stripe-js";
    
    export default function CheckoutForm() {
      // useStateに型を追加した。
      const [succeeded, setSucceeded] = useState(false);
      const [error, setError] = useState<string | null>(null);
      // 下記のstringの型をanyにすると最後のエラーが取れる。
      const [processing, setProcessing] = useState<string | boolean>('');
      const [disabled, setDisabled] = useState(true);
      const [clientSecret, setClientSecret] = useState('');
      const stripe = useStripe();
      const elements = useElements();
    
      useEffect(() => {
        // Create PaymentIntent as soon as the page loads
        window
          .fetch("/create-payment-intent", {
            method: "POST",
            headers: {
              "Content-Type": "application/json"
            },
            body: JSON.stringify({items: [{ id: "xl-tshirt" }]})
          })
          .then(res => {
            return res.json();
          })
          .then(data => {
            setClientSecret(data.clientSecret);
          });
      }, []);
    
      const cardStyle = {
        style: {
          base: {
            color: "#32325d",
            fontFamily: 'Arial, sans-serif',
            fontSmoothing: "antialiased",
            fontSize: "16px",
            "::placeholder": {
              color: "#32325d"
            }
          },
          invalid: {
            color: "#fa755a",
            iconColor: "#fa755a"
          }
        }
      };
      // ここのeventにどうやって型を当てて良いか分からない。
      const handleChange = async (event) => {
        // Listen for changes in the CardElement
        // and display any errors as the customer types their card details
        setDisabled(event.empty);
        setError(event.error ? event.error.message : "");
      };
    
      const handleSubmit = async ev => {
        ev.preventDefault();
        setProcessing(true);
        // ここでも stripe の箇所にエラーで Object is possibly 'null'.とでる。
        const payload = await stripe.confirmCardPayment(clientSecret, {
          payment_method: {
            card: elements.getElement(CardElement)
          }
        });
    
        if (payload.error) {
          setError(`Payment failed ${payload.error.message}`);
          setProcessing(false);
        } else {
          setError(null);
          setProcessing(false);
          setSucceeded(true);
        }
      };
    
      return (
        <form id="payment-form" onSubmit={handleSubmit}>
          <CardElement id="card-element" options={cardStyle} onChange={handleChange} />
          <button
            disabled={processing || disabled || succeeded}
            id="submit"
          >
            <span id="button-text">
              {processing ? (
                <div className="spinner" id="spinner"></div>
              ) : (
                "Pay now"
              )}
            </span>
          </button>
          {/* Show any error that happens when processing the payment */}
          {error && (
            <div className="card-error" role="alert">
              {error}
            </div>
          )}
          {/* Show a success message upon completion */}
          <p className={succeeded ? "result-message" : "result-message hidden"}>
            Payment succeeded, see the result in your
            <a
              href={`https://dashboard.stripe.com/test/payments`}
            >
              {" "}
              Stripe dashboard.
            </a> Refresh the page to pay again.
          </p>
        </form>
      );
    }
    
    
[/code]

### 追記

Object is possibly 'null'.というエラーも出ている。  
下記のように感嘆符を追加して nullの場合は何もしないとする事でエラーを回避出来た。

[code]

    const handleSubmit = async (ev: { preventDefault: () => void; }) => {
        ev.preventDefault();
        setProcessing(true);
        // stripeがnullの場合何もしないと感嘆符を追加した。
        const payload = await stripe!.confirmCardPayment(clientSecret, {
          payment_method: {
            card: elements!.getElement(CardElement)!
          }
        });
    
[/code]

### 追記2

最後のエラーで `disabled`に `Type 'string | boolean' is not assignable to type
'boolean | undefined'. Type 'string' is not assignable to type 'boolean |
undefined'.ts(2322) index.d.ts(2048, 9): The expected type comes from property
'disabled' which is declared here on type
'DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement>' (JSX attribute)
React.ButtonHTMLAttributes<HTMLButtonElement>.disabled?: boolean | undefined`
とエラーが出る。

[code]

    <form id="payment-form" onSubmit={handleSubmit}>
          {/* CardElementに変更があった時にhandleChangeが実行される */}
          <CardElement id="card-element" options={cardStyle} onChange={handleChange} />
          <button
            type="submit"
            // ここにエラーが出る。
            disabled={processing || disabled || succeeded}
            id="submit"
          >
    
[/code]

### 参照

<https://stripe.com/docs/payments/integration-builder>

CardElementComponentをimportしろと書かれているのですが、その後の使い方が書かれていない。  
<https://stackoverflow.com/questions/62680716/what-type-to-use-for-the-
cardelement-in-typescript-for-stripe-react-stripe-j>

カードエレメントのドキュメント  
<https://stripe.com/docs/js/element/events/on_change?type=cardElement>


CC BY-SA 4.0
2021-08-06T02:50:04.077
80631
2021-08-07T13:20:00.380
2021-08-07T05:07:17.360
22565
22565
question
typescript
stripe.jsのサンプルコードをTypeScript化したいが、型の当て方が分からない。


`event`の型は `StripeCardElementChangeEvent` ですね。

  * <https://github.com/stripe/react-stripe-js/blob/d32ba88/src/types/index.ts#L60-L64>

[code]

    import { StripeCardElementChangeEvent } from "@stripe/stripe-js";
    
[/code]

* * *

VSCode上では、 `onChange` にマウスカーソルを合わせると説明がホバー表示されます。

[![VSCode](https://i.stack.imgur.com/iMa9Q.png)](https://i.stack.imgur.com/iMa9Q.png)

あるいは、一旦変数を使わず直接仮実装してみて、

[code]

          <CardElement
            id="card-element"
            options={cardStyle}
            onChange={(event) => {}}
          />
    
[/code]

その上で `event` にマウスカーソルを合わせると、同じように説明が表示されます。

[![画像の説明をここに入力](https://i.stack.imgur.com/f9C16.png)](https://i.stack.imgur.com/f9C16.png)

* * *

追記についてはリファレンスに実装例があります。

  * <https://stripe.com/docs/stripe-js/react#usestripe-hook>
  * <https://stripe.com/docs/stripe-js/react#useelements-hook>

[code]

        if (!stripe || !elements) {
          // Stripe.js has not loaded yet. Make sure to disable
          // form submission until Stripe.js has loaded.
          return;
        }
    
[/code]

どちらかが`null`の場合はsubmitできないように実装します。

* * *

追記2については、エラーメッセージの通り、

> Type 'string | boolean' is not assignable to type 'boolean | undefined'.

`boolean | undefined` 型の `disabled` に対して `string | boolean`
型の値を代入しようとしているためです。  
(型の情報は、前述の通りVSCodeのホバー表示で確認できます)

[code]

      const [processing, setProcessing] = useState<boolean>(false);
    
[/code]


CC BY-SA 4.0
2021-08-06T16:17:43.243
80647
2021-08-07T13:20:00.380
2021-08-07T13:20:00.380
2808
2808
80631
answer