← Back to TypeScript Course | Chapter 28: Real World Projects | Lesson 7 of 14

TypeScript Design System

A design system can use TypeScript to define component props, tokens, variants, and reusable UI contracts. Strong types help keep components consistent.

Core Concept

A typed design system defines reusable UI component props as TypeScript interfaces, so every consumer of a Button or Card component gets compile-time enforcement of exactly which props are valid and required.

Example: Core Concept

typescript
interface ButtonProps {
  variant: "primary" | "secondary";
  onClick: () => void;
}
const props: ButtonProps = { variant: "primary", onClick: () => console.log("clicked") };
console.log(props);

Basic Setup

A basic setup exports each component alongside its typed props interface (export interface ButtonProps { variant: primary | secondary; onClick: () => void }), published as its own versioned package.

Example: Basic Setup

typescript
export interface ButtonProps {
  variant: "primary" | "secondary";
  onClick: () => void;
}
console.log("Component and its typed props interface exported together");

Typed Example

A typed example: using a string-literal union like variant: primary | secondary | danger instead of a plain string means passing variant="primry" (a typo) is a compile error, not a silently-unstyled button in production.

Example: Typed Example

typescript
type Variant = "primary" | "secondary" | "danger";
function applyVariant(variant: Variant) {
  return `btn-${variant}`;
}
console.log(applyVariant("danger"));
// applyVariant("primry") would be a compile error, not a silent style bug

Project Usage

In a real project, a design system's typed props are what let dozens of feature teams consume shared components confidently, since the compiler — not a style guide document — enforces correct usage.

Example: Project Usage

typescript
interface CardProps {
  title: string;
  footer?: string;
}
function renderCard(props: CardProps) {
  return `${props.title}${props.footer ? " - " + props.footer : ""}`;
}
console.log(renderCard({ title: "Stats" }));

Best Practices

Version your design system's typed API deliberately and document breaking prop changes in a changelog, since a prop type change is a breaking change for every consumer even if the runtime behavior looks similar.

Example: Best Practices

typescript
// CHANGELOG.md: "v2.0.0: ButtonProps.variant no longer accepts 'default'"
interface ButtonProps {
  variant: "primary" | "secondary";
}
console.log("Breaking prop changes documented in a changelog");

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.