react-datetime icon indicating copy to clipboard operation
react-datetime copied to clipboard

Typings exported wrong

Open bsl-zcs opened this issue 5 years ago • 1 comments

I'm Submitting a ...

[x] Bug report
[ ] Feature request
[ ] Support request

Steps to Reproduce

import the library as in typescript docs section import * as Datetime from 'react-datetime'; use the component anywhere return <Datetime />; compile with typescript having allowSyntheticDefaultImports: false and open in a browser

Expected Results

the component should be imported and used correctly

Actual Results

the module itself is passed to React.createElement instead of component and in runtime it breaks with message "Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object."

Other Information (e.g. stacktraces, related issues, suggestions how to fix)

that's because the component was migrated to ES6 class declaration with proper default export while typings remained for module.exports = Datetime

it's clearly a bug, affecting any codebase with a strict default imports policy, and the possible workaround is quite ugly:

import * as DatetimeModule from 'react-datetime';
const Datetime = (DatetimeModule as any).default;

on the other hand the fix is so trivial (just add default to export in .d.ts) that i've attempted to perform it right here in github's web interface (#769), only to realize that it is a really breaking change for all typescript users who imports it in old way.

now i see three possible options:

  1. just ignore it, leave the wrong typings and let users with disallowed synthetic imports to use the workaround (or stay on v2)
  2. fix the typings and make a major release to adhere to semver
  3. restore the old-fashioned export in the component to make it compatible with existing typings again

in my opinion the third option isn't pretty but is most practical.

bsl-zcs avatar Jan 09 '21 01:01 bsl-zcs

The workaround that worked for me was this:

import { FC } from 'react';
import * as DatetimeModule from 'react-datetime';
import { DatetimepickerProps } from 'react-datetime';

import 'moment-timezone';
import './style.css';

/**
 * This makes typescript work with the react-datetime module
 */
const Datetime: FC<DatetimepickerProps> = (() => {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  let value = DatetimeModule as any;
  while ('default' in value) value = value.default;
  return value;
})();

export default Datetime;

wellermiranda avatar Jun 07 '23 20:06 wellermiranda