Skip to content

Commit

Permalink
fix: declarations of ContentSwitcher, Slider, SkeletonIcon (#15382)
Browse files Browse the repository at this point in the history
Addresses errors like:

TS2305: Module '"@carbon/react"' has no exported member 'ContentSwitcher'.
12 import { ContentSwitcher } from "@carbon/react";

This contains two types of fixes:

Whenever the underlying component is written in Typescript, the index file needs
to be named index.ts. If it's named index.js, the build won't even generate an
index.d.ts file. (The index file can also be named index.tsx, but that doesn't
make sense unless it contains React markup.)

I updated createClassWrapper() so that Typescript knows the type of the returned
functional component:

export function createClassWrapper<Props>(
  Component: ComponentClass<Props>
): FunctionComponent<Props> {
  ...
}

Note that the generated index.d.ts are a bit weird, for example

/// <reference types="react" />
declare const Slider:
   import("react").FunctionComponent<import("./Slider").SliderProps>;

If I add casting to the index.ts files themselves, ex:

const Slider = createClassWrapper(SliderComponent) as FC<SliderProps>;

That generates more canonical index.d.ts files:

import { FC } from "react";
import { SliderProps } from './Slider';
declare const Slider: FC<SliderProps>;

(So I can do that if you like.)

Of course, the createClassWrapper() calls should be temporary, as all remaining
class components should be converted to functional components.

Refs #13550, #12557, #13574.
  • Loading branch information
wkeese committed Dec 19, 2023
1 parent 46222a7 commit b2cc298
Show file tree
Hide file tree
Showing 5 changed files with 10 additions and 8 deletions.
Expand Up @@ -5,9 +5,12 @@
* LICENSE file in the root directory of this source tree.
*/

import { ComponentClass } from 'react';
import { createClassWrapper } from '../../internal/createClassWrapper';
import ContentSwitcherCarbon from './ContentSwitcher';
import ContentSwitcherCarbon, { ContentSwitcherProps } from './ContentSwitcher';

const ContentSwitcher = createClassWrapper(ContentSwitcherCarbon);
const ContentSwitcher = createClassWrapper(
ContentSwitcherCarbon as ComponentClass<ContentSwitcherProps>
);
export default ContentSwitcher;
export { ContentSwitcher };
Expand Up @@ -5,22 +5,21 @@
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import React, { ComponentClass, FunctionComponent } from 'react';

/**
* Wrap a class component with a functional component. This prevents an end-user
* from being able to pass `ref` and access the underlying class instance.
*
* @param {ReactNode} Component
* @returns {ReactNode}
*/
export function createClassWrapper(Component) {
export function createClassWrapper<Props>(
Component: ComponentClass<Props>
): FunctionComponent<Props> {
function ClassWrapper(props) {
return <Component {...props} />;
}

const name = Component.displayName || Component.name;
ClassWrapper.displayName = `ClassWrapper(${name})`;

return ClassWrapper;
return ClassWrapper as FunctionComponent<Props>;
}

0 comments on commit b2cc298

Please sign in to comment.