reexporting: type declarations, library wrappers, oh my

2021-05-21

 | 

~2 min read

 | 

313 words

In refactoring some code recently, I moved the definitions of some times from one file to another. This broke a number of other files which were expecting the type definitions to come from the original location.

Instead of updating the imports on all of the down stream files, I decided to reexport the definitions.

For example, the diffs might look something like the following

newFile.ts
+ export interface GenericInterface {
+     /*...*/
+ }
export type ExtendedInterface = GenericInterface & {extended: boolean}
originalFile.ts
+ import { GenericInterface, ExtendedInterface } from "./newFile"
+ export { GenericInterface, ExtendedInterface }
+
- export interface GenericInterface {
-     /*...*/
- }
- export type ExtendedInterface = GenericInterface & {extended: boolean}

Meanwhile, other files can carry on importing from the original file as usual.

otherFile.ts
import { GenericInterface, ExtendedInterface } from "./originalFile"

While this is one approach, RIP Tutorial outlines a few others as well.

One of my favorites is the idea of re-exporting a bundle, particularly because it allows for overriding. One potential use case for this is when you want to create a wrapper around a bundled import of a third party library (ex. axios, testing-library, etc.), which I wrote about in greater detail in Jest: Abstract Away Utilities With moduleDirectories. One illustrative example was the following:

libraryWrapper.ts
import { render as rtlRender } from "testing-library/react"

function render(ui, { theme = themes.dark, ...options } = {}) {
  function Wrapper({ children }) {
    return <ThemeProvider theme={theme}>{children}</ThemeProvider>
  }
  Wrapper.propTypes = {
    children: PropTypes.node,
  }

  return rtlRender(ui, { wrapper: Wrapper, ...options })
}

export * from "testing-library/react"
export { render }

The important thing to see here is that we’re exporting all of testing-library/react from the libraryWrapper, which includes a method render, but we’re overriding that version of render with the one we defined. While this example is not about types, the same principles apply.



Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!