0

I am fairly new to Typescript and have one question about it.

In React, I encountered a situation whereby the state of a component can be undefined or a number. And I have a function that must use that particular state object as argument to dispatch action (let say calling API), and the argument cannot be undefined in order to call the API. Code is below.

 interface IState {
   someId?: number;
 }


 const mapDispatchToProps = (dispatch: Dispatch): IPropsFromDispatch => ({
   getSettings: someId => dispatch(getRequest(someId)),
 });

 class someComponent extends React.PureComponent<IProps, IState> {
  
   public constructor(props: IProps) {
     super(props);

     this.state = {
       someId: undefined
     };
   }

   public componentDidUpdate(prevProps: IProps, prevState: IState) {
     if (this.state.someId !== prevState.someId) {
       this.props.getSettings(this.state.someId);
     }
   }

   public render() {
     return (
       <Dropdown
        handleOnSelect={(e) => {this.setState({someId: e.target.value })} }
       />
     )
   }
 }

Basically the someId state initially is undefined, but after selecting through dropdown, it will set the state for someId and trigger the dispatch getSettings action. If I specify type format of the dispatch,

 interface IPropsFromDispatch {
   getSettings(someId: number): void;
 }
 

it will throw me an error saying

Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
Type 'undefined' is not assignable to type 'number'.

The error will be gone if I do this of course

interface IPropsFromDispatch {
   getSettings(someId?: number): void;
}

But I dont think this is recommended in using Typescript, since the dispatch action expects to have the someId as a number, not undefined, to be able to work. Or am I wrong? How should I do this?

1

4 Answers 4

2

You could check that state.someId is truthy:

 if (this.state.someId && this.state.someId !== prevState.someId) {
   this.props.getSettings(this.state.someId);
 }
Sign up to request clarification or add additional context in comments.

Comments

1

You can't set it to undefined directly unless the type would be number | undefined. Either use null as a default value or simply set this.state = {} which will result in state.someId being undefined (since it is not set).

Comments

1

What your are looking for are implicit type casts. Lets refer to the usage of getSettings

public componentDidUpdate(prevProps: IProps, prevState: IState) {
  if (this.state.someId !== prevState.someId) {
    this.props.getSettings(this.state.someId);
  }
}

If you add a null check typescript will implicitly cast number | undefined to number

public componentDidUpdate(prevProps: IProps, prevState: IState) {
  if (this.state.someId && this.state.someId !== prevState.someId) {
    this.props.getSettings(this.state.someId); // someId is now of type number
  }
}

1 Comment

Thanks for your help. But I gotta pick one to mark as solution. So I picked the earliest answer that is similar to your solution.
0

I can't answer for the React part but typescript is behaving like expected You define someId as undefined upon initialisation. Use your second signature and check for the truthyness of the value and it will be casted as a number pass the if

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.