1. ホーム
  2. reactjs

[解決済み] 未定義」の可能性があるオブジェクトを呼び出すことができません.ts(2722)

2022-03-04 08:27:53

質問

ボタンコンポーネントを持っています。私はこのコンポーネントに、単に1つの onClick プロップは、私が定義した多くのオプションのプロップの中から選択します。

const Button = (props: ButtonProps) => {
    const handleClick: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement> = e => {
        props.onClick(e);
    }
    return (
        <StyledButton onClick={handleClick}>
            {props.children}
        </StyledButton>
    );
};

それから、こんな風に使っています。

<Button onClick={(e) => {
    console.log(e);
}}>Click me!</Button>

さて、質問にあるエラーのように、オブジェクトが未定義である可能性はどうでしょうか?私は明らかに関数を渡していますし、それも型定義に従って渡しています。つまり、私はオブジェクトを渡しているのです。単純なことです。

...
onClick?: React.MouseEventHandler<HTMLElement>
...

このプロジェクトでは、最近さらにいくつかの厳しいチェックを追加しています。

"strictFunctionTypes": true,
"strictNullChecks": true

strict:true がすでに存在するため、このエラーは発生しませんでした。

ここで何が問題なのでしょうか?

アップデート - タイプを追加

export interface IBaseButtonProps {
    type?: ButtonType;
    disabled?: boolean;
    size?: ButtonSize;
    block?: boolean;
    loading?: boolean | { delay?: number };
    icon?: string;
    className?: string;
    prefixCls?: string;
    children?: React.ReactNode;
}

export type AnchorButtonProps = {
    href: string,
    target?: string,
    onClick: React.MouseEventHandler<HTMLElement>
} & IBaseButtonProps & Omit<React.AnchorHTMLAttributes<any>, 'type' | 'onClick'>;


export type NativeButtonProps = {
    onClick: React.MouseEventHandler<HTMLElement>,
    htmlType?: ButtonHTMLType
} & IBaseButtonProps & Omit<React.ButtonHTMLAttributes<any>, 'type' | 'onClick'>;

export type ButtonProps = Partial<AnchorButtonProps & NativeButtonProps>

注意事項

可能な解決策は、プロップを再構築し、デフォルトプロップを追加することです。あるいは defaultProps をReactから取得しました。しかし、Typescriptで本当にそれを要求すべきかどうかはわからない。

どのように解決するのですか?

<ブロッククオート

さて、質問にあるように、オブジェクトが未定義である可能性があるのはなぜでしょうか?[sic]です。

の使用は Partial<T> を中心に export type ButtonProps = Partial<AnchorButtonProps & NativeButtonProps> 原因 onClick をオプションにすることができます。私たちが Partial<T> を受信すると、すべてのプロパティは ? となり、オプションとなる。つまり、すべて未定義とすることができる。

修正には2つのアプローチがあり、1つは ButtonProps と同じです。 onClick がオプションであることを確認し、さらに onClick を定義してから呼び出す(修正1)、もうひとつは ButtonProps を作るために onClick が必要です(修正2、3)。

修正1: onClick はオプションのまま

を使用します。 ButtonProps を確認し、その後に onClick が定義されていることを確認してから呼び出す。これは antdが行うこと を、コメントでリンクしていただいたコードに追加しました。

const Button = (props: ButtonProps) => {
  const handleClick: React.MouseEventHandler<
    HTMLButtonElement | HTMLAnchorElement
  > = e => {
    if (props.onClick) props.onClick(e); // works
  };
};

修正2 onClick が必須となります。

変更 ButtonProps を適用しないことで PartialNativeButtonProps :

type ButtonProps1 = Partial<AnchorButtonProps> & NativeButtonProps;

const Button1 = (props: ButtonProps1) => {
  const handleClick: React.MouseEventHandler<
    HTMLButtonElement | HTMLAnchorElement
  > = e => {
    props.onClick(e); // works
  };
};

3を修正する。 onClick も必須となります。

を定義します。 RequireKeys この型は、オプションでないキーを指定することができます。

type RequireKeys<T, TNames extends keyof T> = T &
  { [P in keyof T]-?: P extends TNames ? T[P] : never };

type ButtonProps2 = RequireKeys<ButtonProps, "onClick">;

const Button2 = (props: ButtonProps2) => {
  const handleClick: React.MouseEventHandler<
    HTMLButtonElement | HTMLAnchorElement
  > = e => {
    props.onClick(e); // works
  };
};

の答えは マッピングされた型:オプションのモディファイアを削除する をどのように定義したかについては、さらに詳しい情報があります。 RequireKeys<T> .