arqex / react-datetime

A lightweight but complete datetime picker react component.
2k stars 870 forks source link

Typings exported wrong #770

Open bsl-zcs opened 3 years ago

bsl-zcs commented 3 years ago

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.

wellermiranda commented 1 year ago

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;