remarkablemark/html-react-parser

Type errors with v5.0.0

Closed this issue ยท 6 comments

The following code gives two errors:

const options: HTMLReactParserOptions = {
    replace: (domNode: DOMNode) => {
      if (!(domNode instanceof Element)) return
      if (domNode.name === 'a') {
        domNode.attribs.target = '_blank'
        domNode.attribs.rel = 'noopener noreferrer'
        return domNode // error 1
      }
      if (['html', 'head', 'body'].includes(domNode.name)) {
        return <>{domToReact(domNode.children, options)}</> // error 2
      }
  }
}

Error 1:

Type '(domNode: DOMNode) => Element | JSX.Element | undefined' is not assignable to type '(domNode: DOMNode) => string | boolean | void | Element | null'.
  Type 'Element | JSX.Element | undefined' is not assignable to type 'string | boolean | void | Element | null'.
    Type 'Element' is not assignable to type 'string | boolean | void | Element | null'.
      Type 'Element' is missing the following properties from type 'ReactElement<any, any>': props, keyts(2322)

It seems HTMLReactParserOptions's replace expects JSX.Element instead of domhandler's Element

Error 2:

Argument of type 'ChildNode[]' is not assignable to parameter of type 'DOMNode[]'.
  Type 'ChildNode' is not assignable to type 'DOMNode'.
    Type 'CDATA' is not assignable to type 'DOMNode'.
      Type 'CDATA' is missing the following properties from type 'Element': name, attribs, tagName, attributests(2345)

Expected Behavior

There's no type errors

Actual Behavior

Build fails.

Steps to Reproduce

Use the above code

Reproducible Demo

Environment

  • Version: v5.0.0
  • Platform: React & Vite
  • Browser: Chrome
  • OS: macOS

Keywords

Type error

For the 1st error, can you return void since the return type should either be a React element or void (returning the domNode shouldn't really do anything):

-        return domNode // error 1
+        return

For the 2nd error, can you use type assertion:

-        return <>{domToReact(domNode.children, options)}</> // error 2
+        return <>{domToReact((domNode as Element).children as DOMNode[], options)}</>

Preferably you should check domNode instanceof Element instead of domNode as Element to prevent runtime errors.

You can import Element and DOMNode from:

import { Element, DOMNode } from 'html-react-parser';

Thanks, the method works.

I decided to add back the object return type for replace option in order to fix error 1. See #1129

` const options: HTMLReactParserOptions = {
replace: (domNode: DOMNode) => {
if (!(domNode instanceof Element)) return;
if (domNode.name === "ul") {
return (


    {domToReact(domNode.children as DOMNode[])}

);
}

  if (domNode.name === "li") {
    return (
      <li className="flex gap-2 items-center ">
        <Icons.PinkArrowMarker />
        {domToReact(domNode.children as DOMNode[])}
      </li>
    );
  }
},

};`
Only first condition is getting replaced, can anyone help me with this?

@Bkumar48 can you open a new issue and provide a reproducible example?