The compiler preserves TypeScript type information through compilation. Adapters use it to generate type-safe templates.

Props in client components are reactive — see Props Reactivity. This page covers typing patterns.

#Defining Props

interface GreetingProps {
  name: string
  greeting?: string
}

export function Greeting(props: GreetingProps) {
  return <h1>{props.greeting ?? 'Hello'}, {props.name}</h1>
}

#Default Values

Use nullish coalescing (??) on the props object:

function Button(props: { variant?: 'default' | 'primary'; children?: Child }) {
  const variant = props.variant ?? 'default'
  return <button className={variant}>{props.children}</button>
}

For initial-value-only props, default parameter syntax works. Add @bf-ignore to suppress the BF043 destructuring warning:

// @bf-ignore props-destructuring
function Counter({ initial = 0 }: { initial?: number }) {
  const [count, setCount] = createSignal(initial)
  return <button onClick={() => setCount(n => n + 1)}>{count()}</button>
}

#Extending HTML Attributes

Extend HTML attribute types for components wrapping native elements:

import type { ButtonHTMLAttributes } from '@barefootjs/jsx'

interface ButtonProps extends ButtonHTMLAttributes {
  variant?: 'default' | 'primary' | 'destructive'
  size?: 'sm' | 'md' | 'lg'
}

function Button(props: ButtonProps) {
  const variant = props.variant ?? 'default'
  const size = props.size ?? 'md'
  const classes = `btn btn-${variant} btn-${size} ${props.className ?? ''}`

  return <button className={classes} {...props}>{props.children}</button>
}

Callers can pass standard button attributes (type, disabled, aria-label, etc.) alongside custom props.

#Rest Spreading

Rest spreading captures values once, so use it for server components or non-reactive attributes:

function Card(props: { title: string; children?: Child } & HTMLAttributes) {
  return (
    <div className={props.className}>
      <h2>{props.title}</h2>
      {props.children}
    </div>
  )
}
<Card title="Dashboard" className="shadow-lg" data-testid="dashboard-card">
  <p>Content</p>
</Card>

#Type Preservation

The compiler carries TypeScript type information through the IR. Each adapter uses it for type-safe server output. See Adapters for backend-specific type mapping.