Argument of type 'HTMLElement | null' is not assignable to parameter of type 'Element'. Type 'null' is not assignable to type 'Element'.ts(2345)
Solution 1
Since getElementById
possibly returns null. So you just simply check before using like:
function Portal1({ children }) {
return portalDiv ? ReactDOM.createPortal(<>{children}</>, portalDiv) : null;
}
Solution 2
Other people have answered that you should add a null-check, but Typescript also has a non-null assertion that you can use when you are sure that the value is never null by adding the !
operator to the end of your statement:
const portalDiv = document.getElementById('#your-element')!;
Solution 3
So I dont know if anyone is still having this problem but there's an easier and straightforward solution to this.
simply declare the modal element with "as" keyword
const modalRoot = document.getElementById("modal-root") as HTMLElement;
This removes the error.
I suggest looking through this great react-typescript cheatsheet.
https://github.com/typescript-cheatsheets/react
Solution 4
getElementById
can return null
, but createPortal
doesn't accept null
.
If you know the portal div will exist, make the code explicit about that:
const portalDiv = document.getElementById('portal');
if (!portalDiv) {
throw new Error("The element #portal wasn't found");
}
That will allow TypeScript to narrow the type of the constant, removing the | null
part of the type. It also gives you a nice proactive warning if someone changes things such that the div isn't there when this code runs anymore.
Solution 5
I think the best solution to this is not to make it either null or HTMLDIVElement but rather in the use-case try to let typescript know that the DivElement might be empty at the moment, but you will take responsibility of it by just using "!" symbol.
Code sample below:
import React, {useEffect} from 'react';
import ReactDOM from 'react-dom';
import './modal-portlet.style.scss';
const modalRoot = document.getElementById('modalRoot');
type Props = {
children: JSX.Element;
};
const ModalPortlet: React.FC<Props> = ({children}): JSX.Element => {
const divContainer = window.document.createElement('div');
divContainer.setAttribute('class', 'modal-container');
useEffect(() => {
/**********
* immediately the component mount append @divContainer as the childNode of @modalRoot in the DOM
**********/
modalRoot!.appendChild(divContainer);
return () => {
modalRoot!.removeChild(divContainer);
};
});
/************
* return the createPortal api that takes the children(JSX) and inject it into @divContainer which is already a childNode of @modalRoot
************/
return <>{ReactDOM.createPortal(children, divContainer)}</>;
};
export default ModalPortlet;
Kishore
Hi there, I am an application developer, CSE graduate and I am more into practical programming. I like solving possible daily life problems using codes.
Updated on January 23, 2022Comments
-
Kishore over 2 years
I have index.html
<body> <div id="portal"></div> <div id="root"></div> </body>
and want to use the component below in separate
portal div
thanroot div
,import React from 'react'; const portalDiv = document.getElementById('portal'); function Portal1(props) { return ReactDOM.createPortal( <div> {props.children} <div/>, portalDiv); //here } export default Portal1;
But I am getting this error, Argument of type 'HTMLElement | null' is not assignable to parameter of type 'Element'. Type 'null' is not assignable to type 'Element'.ts(2345) in VScode.
I am using Typescript. Please help.
-
Kishore over 3 yearsYeah, good one indeed. (for added info, some time, typescript, probably latest, suggest to use
?
at same place instead of!
. works fine. -
Kishore about 3 yearsyeah, that might work, but we call that as inline typecasting, i.e., we're just changing type in place. still I feel, if there is null values, that is, if the div doesn't exist, it will still give null. and the typecasting null as HTMLElement might give error. did you try applying changes?
-
Oluwaseyitan Baderinwa about 3 yearsI did apply it and it seemed to be the only way to fix the error. And the cheatsheet gives more details as to why this method is recommended. Btw, the HTMLElement type is Element|null type so I don't think it'll give an error. I already tested it
-
gcr about 3 years! back at ya! I don't know if the above if () {} solutions were possible in my case (maybeI just don't know how) as the jsx library (react-modal) expects a callback returning an html element, not the element directly, so I don't know at what point I could have done the check and got TS to recognize it. So glad you shared. I just wanna know if/when I'd be abusing some escape hatch like this. I wanna be a user not an abuser but maybe this is why they created it.
-
Titulum about 3 yearsWell, take a look at this example. The
!
check on line 7 is required, because typescript is not 'smart' enough to see that you already checked whether the value is not null in another function. -
DinoSaadeh about 2 yearskind of a noob to this operator, can you link docs page for this?
-
Titulum about 2 years@DinoSaadeh typescriptlang.org/docs/handbook/release-notes/…
-
Rohan Bhangui about 2 yearswhat does the ! do?