Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

939
Visualizações
Cannot invoke an object which is possibly 'undefined'.ts(2722)

I have a button component. I simply pass it just one onClick prop out of many optional props I've defined:

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

Then I'm using it like this:

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

Now how can as per the error mentioned in question, object be possibly undefined? I'm clearly passing the function to it and that too as per the type definition. So, I'm passing an object to it. Simple enough!

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

I've added a few more strict checks in this project recently and relevant one's are:

"strictFunctionTypes": true,
"strictNullChecks": true

strict:true being already present, this error never occurred.

What's the issue here?

Update - Types added

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>

Notes:

The possible solution is to either destructure the props and add the default prop. Or use defaultProps from React. But not sure if I should require that really with Typescript.

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

With Typescript 3.7+, you can also use optional chaining to invoke the optional prop method:

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

You can read more about using optional chaining - https://www.stefanjudis.com/today-i-learned/optional-chaining-helps-to-avoid-undefined-is-not-a-function-exceptions/

over 4 years ago · Santiago Trujillo Relatório

0

Now how can as per the erro mentioned in question, object be possibly undefined? [sic]

The use of Partial<T> around export type ButtonProps = Partial<AnchorButtonProps & NativeButtonProps> causes onClick to be optional. When we use Partial<T>, all the properties receive the ? and thus become optional, which means that all of them can be undefined.

There are two approached to a fix: one is to keep ButtonProps the same with onClick as optional, and to check that onClick is defined before calling it (fix 1); the other is to change ButtonProps to make onClick required (fix 2 and 3).

Fix 1: onClick remains optional

Use the ButtonProps that you already have, and then check that onClick is defined before calling it. This is what antd does in the code you linked in the comments.

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

Fix 2: onClick becomes required

Change ButtonProps by not applying the Partial to the NativeButtonProps:

type ButtonProps1 = Partial<AnchorButtonProps> & NativeButtonProps;

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

Fix 3: onClick becomes required too

Define a RequireKeys type, which lets you to specify the keys that are not optional.

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

The answers to Mapped Types: removing optional modifier have more information about how I defined RequireKeys<T>.

over 4 years ago · Santiago Trujillo Relatório

0

Just a clear cut answer

if (props.onClick) props.onClick(e);

if you are defining a function props and want it to be optional, define it as,

export type ButtonProps = {
  function?: () => void;
};

Explanation: If you want to use a function as props, there may be instances when you want to pass that function (as props) and there may be other instances where you don't want to pass it.

for example,

Common Code WHERE calling the <Home/> component, say index.ts/index.js

function myfunction(){
  //do something
  alert("hello")
}

return (
  <>
     <Home myfunction={myfunction}/>    //passing prop
     <Home/>                            // not passing
  </>
)

In JS, home.js

export default function Home({myfunction}) {
  const const1 = "Hello World"
  return (
    //do something
    myfunction();      //IMPORTANT line
  )
}

Now, its almost equivalent in TS, home.ts

In TS, we define types of everything. So, in that case we have to define type of this function myfunction also, that we are passing.

So, for this function, we realise that,

  • It recieves no params, so () (empty parenthesis) is enough, if any params are there, we need to define types for them also.
  • Returns nothing, so return type void
export type HomeProps = {
  myfunction?: () => void;
};

export default function Home({ myfunction }: HomeProps) {
  const const1 = "Hello World"
  return (
    //do something
    if (myfunction) myfunction();      //IMPORTANT line
  )
}

Hint: above answer

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda