krz-icons logo
Blog

Using Icon Libraries with TypeScript in React

How to type icon props in TypeScript React apps — passing icons as props, creating icon registries, typing size and color, and working with the KrzIcon type.


TypeScript and icon libraries go well together, but the type patterns are not always obvious. This guide shows every common pattern for typing icons in React.

The KrzIcon type

krz-icons exports a KrzIcon type that represents any icon component. Use it to type props that accept an icon.

import type { KrzIcon } from "krz-icons";

// A button that accepts any icon component
interface IconButtonProps {
  icon: KrzIcon;
  label: string;
  onClick?: () => void;
}

function IconButton({ icon: Icon, label, onClick }: IconButtonProps) {
  return (
    <button onClick={onClick} aria-label={label}>
      <Icon size={18} />
    </button>
  );
}

The KrzIcon type is a ForwardRefExoticComponent with the full prop interface, so TypeScript will catch invalid props at the call site.

Passing icons as props

import { Bell, Home, Search } from "krz-icons";
import type { KrzIcon } from "krz-icons";

const navItems: { label: string; icon: KrzIcon; href: string }[] = [
  { label: "Home",     icon: Home,   href: "/" },
  { label: "Search",   icon: Search, href: "/search" },
  { label: "Alerts",   icon: Bell,   href: "/alerts" },
];

Icon registries

When icon names come from data (for example, a CMS or config file), create a registry map.

import {
  Home, Bell, Search, Settings, User, Mail,
} from "krz-icons";
import type { KrzIcon } from "krz-icons";

const iconRegistry: Record<string, KrzIcon> = {
  home:     Home,
  bell:     Bell,
  search:   Search,
  settings: Settings,
  user:     User,
  mail:     Mail,
};

function DynamicIcon({ name, ...props }: { name: string } & React.SVGProps<SVGSVGElement>) {
  const Icon = iconRegistry[name];
  if (!Icon) return null;
  return <Icon {...props} />;
}

Typing size and color props

If you build wrapper components that accept size or color as props, you can re-use the types from the package.

import type { KrzIconProps } from "krz-icons";

// Subset of the icon's own props
type IconSize = KrzIconProps["size"];   // number | string | undefined
type IconColor = KrzIconProps["color"]; // string | undefined

Generic component with constrained icons

When you want a component that accepts one of a specific set of icons, use a union type or a const array.

import { CheckCircle, AlertCircle, AlertTriangle, Info } from "krz-icons";
import type { KrzIcon } from "krz-icons";

const STATUS_ICONS = {
  success: CheckCircle,
  error:   AlertCircle,
  warning: AlertTriangle,
  info:    Info,
} satisfies Record<string, KrzIcon>;

type Status = keyof typeof STATUS_ICONS;

function StatusBadge({ status, label }: { status: Status; label: string }) {
  const Icon = STATUS_ICONS[status];
  return (
    <span className="flex items-center gap-2">
      <Icon size={16} title={status} />
      {label}
    </span>
  );
}

Autocomplete for icon names

Named imports from krz-icons trigger VS Code autocomplete. Type the first few characters of an icon name after the opening brace and hit Ctrl+Space:

import { Ho|  } from "krz-icons";
//              ^ autocomplete suggests Home, Hospital, HospitalBed, ...

Strict null checks

If you look up an icon from a registry at runtime, TypeScript knows the result might be undefined when you use an index signature. Guard it before rendering.

const Icon = iconRegistry[name];
if (!Icon) return <span aria-label={name} />;
return <Icon size={size} />;

Summary

The KrzIcon type covers the most common patterns. For dynamic registries, use Record<string, KrzIcon> and guard against missing entries. For constrained sets, use satisfies Record<string, KrzIcon> to get both the type safety and the exact component references.

Full icon props reference →


Looking for icons?

Browse 20 000+ free, MIT-licensed SVG and React icons.