1

I am new to Typescript and I have an error I don't understand in React Typescript. I suspect that it comes from the way I write my interface but I am not sure.

First I call my CellEditable component

<CellEditable value={'Hello'} onChange={() => {}} />

CEllEditable has an isEditable state that toggles InputText on click

CellEditable.tsx

import React, { useState } from 'react'
import Cell from './Cell.comp'
import InputText from './InputText.comp'

interface CellEditableProps {
  value: string
  onChange?: () => void
}

const renderCellInput = (type: string, opts: any) => {
  switch (type) {
    case 'text':
      return <InputText {...opts} />
    default:
      return <div>Missing!</div>
  }
}

const CellEditable = (props: CellEditableProps) => {
  const { value, onChange } = props
  const [isEditing, setEditing] = useState<boolean>(false)

  const handleClick = () => setEditing(!isEditing)
  const handleBlur = () => setEditing(!isEditing)

  const opts = {
    value,
    helpers: {
      onBlur: handleBlur,
      onChange
    }
  }

  return (
    <div onClick={handleClick}>
      {
        isEditing
        ? renderCellInput('text', opts)
        : <Cell value={value} />
      }
    </div>
  )
}

export default CellEditable

InputText.tsx

import React from 'react'

interface InputTextProps {
  value?: string
  helpers?: HelpersProps
}

interface HelpersProps {
  onChange?: () => void
  onBlur?: () => void
}

const InputText = (props: InputTextProps) => {
  const { value, helpers } = props
  console.log('propsInputText:', props) // Empty object in the console
  
  return (
    <input type={'text'} value={value} onChange={helpers.onChange} onBlur={helpers.onBlur} />
  )
}

export default InputText

The issue is:

  1. helpers.onChange gets this error "Object is possibly 'undefined'. TS2532"
  2. console.log('propsInputText:', props) in InputText.tsx output an empty object.

Is it an issue with typescript and the way I write my interface?

2
  • Moving onChange and onBlur into InputTextProps and removing the helpers object seems to works. But 1) The issue doesn't happen in a CodeSandbox environment, only in my local react typescript environment 2) I would prefer to pass handlers into a container object in props 3) I want to better understand how TS interface and optional props work. Commented Jan 27, 2021 at 13:32
  • A previous answer that has been deleted suggested to test for the existence of OnChange and onBlur keys in the helpers object like so helpers!.onChange. How about destructuring the helpers props: const { value, helpers: { onChange, onBlur } } = props. I get the following error Property 'onChange' does not exist on type 'HelpersProps | undefined'.ts (2339) Commented Jan 27, 2021 at 13:39

3 Answers 3

3

the helpers property in InputTextProps and the onChange property in your HelpersProps are optional. either make them required by removing the question mark or assign to them a default values when destructuing.

const { value, helpers = {} } = props;
const { onChange = () => {} } = helpers;

 return (
    <input type={'text'} value={value} onChange={onChange} onBlur={helpers.onBlur} />
  )
Sign up to request clarification or add additional context in comments.

Comments

0

inside your interface:

interface CellEditableProps {
  value: string
  onChange?: () => void
}

you placed a ? after onChange, that tells the compiler that it can be not passed and hence you get "Object is possibly 'undefined'

To remedy this solution either you can use onChange with ! like onChange!. This thells compiler that you are sure that onChange will not be null. But this is a bad approach.

What you should do is check if it is not null or undefined and then proceed:

if(onChange) {
    ...do your stuff here
}

Comments

0

your interface declaration clearly states that these can indeed be undefined (? marks these properties as optional). You'll need to check for their existance or fill them.

const value = props.value || '';
const helpers = {
   onChange: () => {},
   onBlur: () => {},
   ...(props.helpers || {}),
};

return (
    <input type={'text'} value={value} onChange={helpers.onChange} onBlur={helpers.onBlur} />
)

or similar.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.