# percentage

Validate percentage values

Canonical URL: https://docs.paradoc.dev/sdk/primitives/percentage/

Validate percentage values. The Percentage primitive ensures numeric values represent valid percentages with optional range constraints.

## Examples

### Creating percentages

```ts
// Direct validation
const pct = p.percentage(75.5)

// Parse with options
const pct = p.percentage.parse(input, { min: 0, max: 100 })

// Convert from decimal (0.755 → 75.5)
const pct = p.percentage.fromDecimal(0.755)

// Convert to decimal (75.5 → 0.755)
const decimal = p.percentage.toDecimal(75.5)

// Check validity without throwing
if (p.percentage.isValid(50)) {
  console.log('Valid percentage')
}
```

### Parsing external data

```ts
// Parse unknown input (throws on error)
const pct = p.percentage.parse(userInput)

// Safe parsing (returns result object)
const result = p.percentage.safeParse(userInput)
if (result.success) {
  console.log(`Percentage: ${result.data}%`)
} else {
  console.error(result.error.message)
}

// Parse with range constraints
const pct = p.percentage.parse(userInput, { min: 0, max: 100 })
```

### Using with forms

```ts
const form = p.form({
  name: 'discount',
  fields: {
    discountRate: { type: 'percentage', label: 'Discount Rate', min: 0, max: 50 },
    taxRate: { type: 'percentage', label: 'Tax Rate' }
  }
})

const filled = form.fill({
  fields: {
    discountRate: p.percentage(15),
    taxRate: p.percentage(8.25)
  }
})
```

## API

### Direct Call

```ts
p.percentage(input: number): number
```

Pass a number for validation. Returns the validated number, rounded to the configured precision (two decimal places by default), or throws on error.

```ts
const pct = p.percentage(75.5)
```

### Static Methods

| Method | Returns | Description |
| --- | --- | --- |
| `parse(input: unknown, options?: PercentageOptions)` | `number` | Parse unknown input (throws on error) |
| `safeParse(input: unknown, options?: PercentageOptions)` | `Result<number>` | Parse unknown input (returns result object) |
| `isValid(input: number, options?: PercentageOptions)` | `boolean` | Check if a number is a valid percentage |
| `fromDecimal(decimal: number)` | `number` | Convert decimal to percentage (0.5 → 50) |
| `toDecimal(percentage: number)` | `number` | Convert percentage to decimal (50 → 0.5) |

### PercentageOptions

| Option      | Type      | Description                             |
| ----------- | --------- | --------------------------------------- |
| `min`       | `number?` | Minimum allowed value                   |
| `max`       | `number?` | Maximum allowed value                   |
| `precision` | `number?` | Decimal places to round to (default: 2) |

## Conversion Helpers

```ts
// Decimal to percentage
p.percentage.fromDecimal(0.5)    // → 50
p.percentage.fromDecimal(0.125)  // → 12.5
p.percentage.fromDecimal(1.5)    // → 150

// Percentage to decimal
p.percentage.toDecimal(50)       // → 0.5
p.percentage.toDecimal(12.5)     // → 0.125
p.percentage.toDecimal(150)      // → 1.5
```

## Validation

The Percentage primitive validates:

* Value must be a finite number (not NaN or Infinity)
* Value must satisfy min/max constraints if provided

```ts
// Valid
p.percentage(0)
p.percentage(100)
p.percentage(50.5)
p.percentage(-10)   // Negative allowed by default
p.percentage(150)   // Over 100 allowed by default

// With constraints
p.percentage.parse(50, { min: 0, max: 100 })  // Valid
p.percentage.parse(150, { min: 0, max: 100 }) // Throws

// Invalid - throws Error
p.percentage(NaN)

p.percentage(Infinity)
```

## Related

* [Primitives Overview](/sdk/primitives) - All available primitives
* [Rating](/sdk/primitives/rating) - Similar numeric validation
* [Percentage Field](/sdk/artifacts/form/field#percentage) - Percentage field type
