Definitelytyped: [react-bootstrap] 'title' prop type (React.ReactNode) conflicts with html 'title' (string)

Created on 1 Mar 2017  路  9Comments  路  Source: DefinitelyTyped/DefinitelyTyped

type 'ReactNode' is not assignable to type 'string'

What types implement

NavDropdown

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/react-bootstrap/index.d.ts#L590

    interface NavDropdownBaseProps extends DropdownBaseProps {
        active?: boolean;
        noCaret?: boolean;
        eventKey?: any;
    }
    type NavDropdownProps = NavDropdownBaseProps & React.HTMLProps<NavDropdown>;
    class NavDropdown extends React.Component<NavDropdownProps, {}> { }

React.HTMLProps

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/react/index.d.ts#L434

    interface HTMLProps<T> extends HTMLAttributes<T>, ClassAttributes<T> {
    }

HTMLAttributes

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/react/index.d.ts#L2041

    interface HTMLAttributes<T> extends DOMAttributes<T> {
    //...
        title?: string;
    //...
    }

What the react-boostrap module actually implements

https://github.com/react-bootstrap/react-bootstrap/blob/master/src/DropdownButton.js#L12

const propTypes = {
  ...Dropdown.propTypes,

  // Toggle props.
  bsStyle: React.PropTypes.string,
  bsSize: React.PropTypes.string,
  title: React.PropTypes.node.isRequired,
  noCaret: React.PropTypes.bool,

  // Override generated docs from <Dropdown>.
  /**
   * @private
   */
  children: React.PropTypes.node,
};

A lot of files might be impacted (not tested yet though)

https://github.com/react-bootstrap/react-bootstrap/search?utf8=%E2%9C%93&q=%27title%3A+React.Proptypes%27&type=Code

Why use 'React.HTMLProps' ?

Injecting all html potential attributes is misleading in IDE, and potentially conflicts with props named like html attributes, like this issue is showing.

  • [ ] I tried using the @types/xxxx package and had problems.
  • [x] I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript
  • [x] I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).
  • [x] [Mention](https://github.com/blog/821-mention-somebody-they-re-notified) the authors (see Definitions by: in index.d.ts) so they can respond.
    @RyanCavanaugh @sandersn @LKay @patsissons @valorize @xuqingkuang @rickydigime @richardjharding @octatone @olmobrutall @TheBosZ @minestarks @kant2002 @jramsay @Strato @ericanderson @csillag

Most helpful comment

I just ran into this issue and wanted to follow-up in case others are struggling with it. I checked out the now closed issue #18524 referenced above by @heatherbooker, however the changes do not address NavdropDown. The react-bootstrap issue 928 indicates that the Navdropdown should support a node as a title so I feel a fix should be implemented.

It looks like the strategy used in this commit for components like DropdownButton could also be used to solve the problem for NavDropdown. I was able to use a similar approach and module augmentation to patch the problem in my app's declarations.

For those who need a quick and dirty fix, here is an example:

declare module 'react-bootstrap' {
    interface ExtendedNavDropdownBaseProps extends NavDropdownBaseProps {
        title?: React.ReactNode;
    }

    type NavDropdownProps = ExtendedNavDropdownBaseProps & Omit<React.HTMLProps<NavDropdown>, 'title'>;
    class NavDropdown extends React.Component<NavDropdownProps> { }
}

Any reason why a pull request shouldn't be made to address this?

All 9 comments

Can you clarify what you think the solution is?

I think we should not use React.HTMLProps<NavDropdown>, it's implicitly setting a lot of props that the react bootstrap lib is not implementing.

Reading the code, it seems that all properties that aren't used by the react component get passed down the chain, where they eventually get applied to the HTML the is emitted.

By this read, the types are correct.

The 'title' property is a prop of the Dropdown and also a HTML attribute, so there is a conflict.

    interface NavDropdownBaseProps extends DropdownBaseProps {
        active?: boolean;
        noCaret?: boolean;
        eventKey?: any;
        title: React.ReactNode
    }

raises :

Type 'ReactNode' is not assignable to type 'string'.
(property) title: string

Beeing new to typescript I searched for a way to 'exclude' properties from an interface but I couldn't.

Intent :

type CustomNavDropDownProps = DropdownBaseProps - {title: string}

It appears we can't remove a property from an interface, so the only solution that comes to me would be not to have 'title' in the first place.

I really have no idea how to fix this :/

You could try
type NavDropdownBaseProps = DropdownBaseProps | { active?: boolean; noCaret?: boolean; eventKey?: any; title: JSX.Element }

This would not remove title: string but at least allow specify JSX node

That's tough. Outside of a feature for typescript the other choice is to change the wording in react bootstrap, which they probably won't do for semver. Does a string not work for the title? Could it be JSX.Element | string?

I think I patched something like this a while back, same issue with title. I'll take a look at my history in a moment to see what the solution was.

UPDATE: turns out it was for a different module type definition, but the same concept was still the issue. my solutions was to do the following:

// NOTE: this was written quite a while ago, we can probably use more advanced typing operations today to simplify this solution
interface HTMLPropsWithoutTitle<T> extends HTMLProps<T> {
  title?: any;
}

export interface NavDropdownProps extends HTMLPropsWithoutTitle<NavDropdown> {
  // ...
}

Any updates on this?

I just ran into this issue and wanted to follow-up in case others are struggling with it. I checked out the now closed issue #18524 referenced above by @heatherbooker, however the changes do not address NavdropDown. The react-bootstrap issue 928 indicates that the Navdropdown should support a node as a title so I feel a fix should be implemented.

It looks like the strategy used in this commit for components like DropdownButton could also be used to solve the problem for NavDropdown. I was able to use a similar approach and module augmentation to patch the problem in my app's declarations.

For those who need a quick and dirty fix, here is an example:

declare module 'react-bootstrap' {
    interface ExtendedNavDropdownBaseProps extends NavDropdownBaseProps {
        title?: React.ReactNode;
    }

    type NavDropdownProps = ExtendedNavDropdownBaseProps & Omit<React.HTMLProps<NavDropdown>, 'title'>;
    class NavDropdown extends React.Component<NavDropdownProps> { }
}

Any reason why a pull request shouldn't be made to address this?

Was this page helpful?
0 / 5 - 0 ratings