Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type 'null' is not assignable to type 'HTMLInputElement' ReactJs

Tags:

I am trying to reference data into reactJS along with typescript. While doing this I am getting below error

Type 'null' is not assignable to type 'HTMLInputElement'

Please let me know what exactly incorrect here, I used documentaiton from React https://reactjs.org/docs/refs-and-the-dom.html but I think I am doing something wrong here. Below is the scope snippet

  class Results extends React.Component<{}, any> {
  private textInput: HTMLInputElement;
  .......
  constructor(props: any) {
    super(props);

    this.state = { topics: [], isLoading: false };

    this.handleLogin = this.handleLogin.bind(this);
    }

     componentDidMount() {.....}

    handleLogin() {
    this.textInput.focus();
    var encodedValue = encodeURIComponent(this.textInput.value);
   .......
}

  render() {
    const {topics, isLoading} = this.state;

    if (isLoading) {
        return <p>Loading...</p>;
    }

    return (
        <div>
              <input ref={(thisInput) => {this.textInput = thisInput}} type="text" className="form-control" placeholder="Search"/>
              <div className="input-group-btn">     
                           <button className="btn btn-primary" type="button" onClick={this.handleLogin}>

   ...............

Any idea what I may be missing here?

like image 433
athenatechie Avatar asked Jan 28 '18 16:01

athenatechie


People also ask

Is not assignable to type null?

The "Type 'string | null' is not assignable to type string" error occurs when a possibly null value is assigned to something that expects a string . To solve the error, use a non-null assertion or a type guard to verify the value is a string before the assignment.

Does not exist on type HTMLAnchorElement?

The error "Property 'href' does not exist on type 'HTMLElement'" occurs when we try to access the href property on an element that has a type of HTMLElement . To solve the error, use a type assertion to type the element as HTMLAnchorElement before accessing the property. This is the index.

How do I cast an element to HTMLElement?

To get HTMLElement from element with TypeScript, we can cast elements to HTMLElement . const nodes = document. querySelectorAll<HTMLElement>("a"); to cast the items in the node list returned by querySelectorAll to HTMLElement .


2 Answers

The error is produced becase the types definitions says input can be null or a HTMLInputElement

You can set "strict": false in your tsconfig.json

Or you can force the input to be HTMLInputElement type

<input ref={thisInput => (this.textInput = thisInput as HTMLInputElement)} type="text" className="form-control" placeholder="Search" />

This way is also valid (using definite assignment assertions (typescript >= 2.7))

<input ref={thisInput => (this.textInput = thisInput!)} type="text" className="form-control" placeholder="Search" />
like image 148
lleon Avatar answered Sep 17 '22 12:09

lleon


This is, indeed, caused by you correct and commendable use of:

"strict": "true"

Which sets a few rules including the all important:

"strictNullChecks": "true"

Handling Potential Nulls

The correct way to handle this is to check that the element isn't in fact null, because almost every method you use to query an element may fail to find one.

In the example below, the if-statement acts as a type guard, so the type of HTMLElement | null is narrowed to just HTMLElement.

const elem = document.getElementById('test');

if (elem) {
  elem.innerHTML = 'Type here is HTMLElement, not null';
}

Handling HTML Element Types

To narrow the type from HTMLElement to HTMLInputElement, you can take an "I know better" approach and use a type assertion (making a class of subtle errors possible):

const example = <HTMLInputElement> elem;

Or you can use a custom type guard to do it properly, the below example takes HTMLElement | null and narrows it to HTMLInputElement if it isn't null, and has the correct tag name:

function isInputElement(elem: HTMLElement | null): elem is HTMLInputElement {
  if (!elem) {
    // null
    return false;
  }

  return (elem.tagName === 'INPUT')
}

The updated type guard call looks like this:

const elem = document.getElementById('test');

if (isInputElement(elem)) {
  console.log(elem.value);
}
like image 43
Fenton Avatar answered Sep 16 '22 12:09

Fenton