microsoft/TypeScript

Imported libraries dropped when spread used on foo: any (new in 2.3)

Closed this issue · 6 comments

This is a new bug in 2.3. When you use a spread in JSX and the type of the variable being spread is "any" some referenced libraries are not kept.

There is also a full (but minimal) example in this repo: https://github.com/luggage66/ts23issue (just npm install && tsc && cat lib/foo.js )

TypeScript Version: 2.3.2

Code

import * as React from 'react';
import * as cx from 'classnames';

export default class FooComponent extends React.Component<any, void> {

    render() {
        let buttonProps; // any

        buttonProps = {
            onClick: () => undefined
        };

        return <button {...buttonProps}>
            <span className={cx('class1', { class2: true })} />
        </button>;
    }
}

Expected behavior:

The output to include require('classnames') (or the equivalent in your configured module system).

Actual behavior:

require('classnames') is missing when {...foo} is used when type of foo is "any".

Using --noImplicitAny will also cause require('classnames') to be in the output.

diiq commented

I am also having dropped imports due to using the spread operator.

However, I have two differences from the reported issue:

  1. noImplicitAny doesn't seem to have an effect -- the imports are trimmed either way, for me.
  2. The object I am spreading is of type {[attributeName: string]: ''}, not any

The outcome is the same, though. With the spread, imports are trimmed for anything that is referenced only in the children of the jsx element. If I remove the spread, everything is okey-dokey; and if I roll back typescript to an earlier version, it's hunky-dory then, too.

Using es6-style modules fixes the problem, but only because it turns off import-trimming entirely :/.

casting to {} fixes it. it's a temporary fix until this is resolved.

yuit commented

@diiq want to make sure I understand your scenario and that the PR address your issue
(Note i use above code with modify spread object type)

import * as React from 'react';
import * as cx from 'classnames';

export default class FooComponent extends React.Component<any, void> {

    render() {
        let buttonProps : {[attributeName: string]: ''}

        buttonProps = {
            onClick: () => undefined
        };

        return <button {...buttonProps}>
            <span className={cx('class1', { class2: true })} />
        </button>;
    }
}
import * as React from 'react';
export default class FooComponent extends React.Component {
    render() {
        // with this line, it'll include the 'classnames' lib
        // let buttonProps: object;
        // with this line, it will not
        let buttonProps; // any
        buttonProps = {
            onClick: () => undefined
        };
        //let i = <span className={cx('class1', { class2: true })} />;
        return React.createElement("button", Object.assign({}, buttonProps),
            React.createElement("span", { className: cx('class1', { class2: true }) }));
    }
}
diiq commented

@yuti that looks right. This is used all over my codebase, so I rolled back to < 2.3 -- which means I haven't verified that what you posted makes the problem occur, but it does look like my situation.

I'm using React and Glamor; it's spreading Glamor's StyleAttribute type that causes the problem, if that helps.

Let me know if you need more info from me.

yuit commented

@diiq thanks for the information. The PR should address your issue as well. @luggage66 @alitaheri @diiq Give tomorrow nightly built a try and let us know