How toSimplify Component Imports with TypeScript Namespaces
If you're building a component that has some props, you probably have a file like this:
components/button.tsx export type ButtonProps = { ... }; export function Button(props: ButtonProps) { ... }
This way anyone using this component can import both the component and the props type.
components/better-button.tsx import { Button, type ButtonProps } from "./button"; export type BetterButtonProps = ButtonProps & { ... }; export function BetterButton(props: BetterButtonProps) { ... }
But notice how you need to import both the Button
and ButtonProps
as separate things, this also force you to name the props type as ButtonProps
instead of just Props
to avoid possible name conflicts (yes you could export it as Props and rename it on import, but that's just most work).
Using TypeScript namespaces, you can combine this into a single imported value.
components/button.tsx export namespace Button { export type Props = { ... } } export function Button(props: Button.Props) { ... }
Now when import this component on our BetterButton component, we can do it this way:
components/better-button.tsx import { Button } from "./button"; export namespace BetterButton { export type Props = Button.Props & { ... }; } export function BetterButton(props: BetterButton.Props) { ... }
Note how we only imported Button but got both the component and the namespace, and inside the namespace we could have more types.
components/button.tsx export namespace Button { export type Variant = "solid" | "ghost" | "outline"; export type Size = "xs" | "sm" | "md" | "lg" | "xl"; export type Props = { variant: Variant; size: Size; } } export function Button(props: Button.Props) { ... }
Now if we want to use them we could import Button and use Button.Variant
or Button.Size
.