Skip to content

ResourcefulIntegerType

The ResourcefulIntegerType class provides comprehensive 32-bit signed integer validation and schema generation for whole number fields. It supports range constraints, exclusive bounds, and multiple validation based on OpenAPI 3.0 specifications.

For complete API reference, see ResourcefulIntegerType.

Overview

ResourcefulIntegerType is designed for 32-bit signed integer values, supporting:

  • Range Validation: Configurable minimum and maximum value constraints
  • 32-bit Precision: Automatically formatted as int32 for OpenAPI compatibility
  • Exclusive Bounds: Support for exclusive minimum and maximum values
  • Multiple Validation: Ensure values are multiples of a specified number
  • Type Safety: Full TypeScript support with validated configuration options

Basic Usage

Simple Integer Validation

typescript
import { ResourcefulIntegerType } from '@nhtio/lucid-resourceful/definitions'

// Basic integer with range constraints
const ageType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 150,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

// Count with positive values only
const countType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 1000000,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

With Decorators

typescript
import { resourcefulColumn } from '@nhtio/lucid-resourceful'

class User extends compose(BaseModel, withResourceful({ name: 'User' })) {
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 0,
      maximum: 150,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: true
  })
  declare age: number

  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 0,
      maximum: 5,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: true
  })
  declare rating: number
}

Configuration Options

Required Options

minimum

  • Type: number
  • Required: Yes

The minimum allowed integer value.

typescript
const positiveType = ResourcefulIntegerType({
  minimum: 1,        // Must be at least 1
  maximum: 100,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

exclusiveMinimum

  • Type: boolean
  • Required: Yes

Whether the minimum value is exclusive (value must be greater than minimum).

typescript
// Value must be > 0 (exclusive)
const exclusiveType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 100,
  exclusiveMinimum: true,  // Value must be > 0
  exclusiveMaximum: false,
  multipleOf: 1
})

// Value can be >= 0 (inclusive)
const inclusiveType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 100,
  exclusiveMinimum: false, // Value can be >= 0
  exclusiveMaximum: false,
  multipleOf: 1
})

maximum

  • Type: number
  • Required: Yes

The maximum allowed integer value.

typescript
const boundedType = ResourcefulIntegerType({
  minimum: -100,
  maximum: 100,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

exclusiveMaximum

  • Type: boolean
  • Required: Yes

Whether the maximum value is exclusive (value must be less than maximum).

typescript
// Value must be < 100 (exclusive)
const exclusiveMaxType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 100,
  exclusiveMinimum: false,
  exclusiveMaximum: true,  // Value must be < 100
  multipleOf: 1
})

multipleOf

  • Type: number
  • Required: Yes

The value must be a multiple of this number.

typescript
// Even numbers only
const evenType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 100,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 2  // Must be divisible by 2
})

// Multiples of 5
const fiveType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 100,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 5  // 0, 5, 10, 15, 20, etc.
})

Common Modifiers

All base interface modifiers are supported:

typescript
// Read-only integer (like auto-increment IDs)
const readOnlyType = ResourcefulIntegerType({
  minimum: 1,
  maximum: 2147483647,  // Max 32-bit signed integer
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1,
  readOnly: true
})

// Nullable integer
const optionalType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 100,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1,
  nullable: true
})

Common Patterns

Age and Demographics

typescript
const ageType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 150,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

@resourcefulColumn.integer({
  type: ageType,
  nullable: true
})
declare age: number

@resourcefulColumn.integer({
  type: ageType,
  nullable: true
})
declare minimumAge: number

Counts and Quantities

typescript
const countType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 999999,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

class Product extends compose(BaseModel, withResourceful({ name: 'Product' })) {
  @resourcefulColumn.integer({
    type: countType,
    nullable: false
  })
  declare stockQuantity: number

  @resourcefulColumn.integer({
    type: countType,
    nullable: false
  })
  declare soldCount: number

  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 1,
      maximum: 99,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: true
  })
  declare minOrderQuantity: number
}

Rating Systems

typescript
// 5-star rating (1-5)
const starRatingType = ResourcefulIntegerType({
  minimum: 1,
  maximum: 5,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

// 10-point scale (0-10)
const scaleRatingType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 10,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

@resourcefulColumn.integer({
  type: starRatingType,
  nullable: true
})
declare rating: number

@resourcefulColumn.integer({
  type: scaleRatingType,
  nullable: true
})
declare score: number

Priority and Order

typescript
const priorityType = ResourcefulIntegerType({
  minimum: 1,
  maximum: 10,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

const sortOrderType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 9999,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

class Task extends compose(BaseModel, withResourceful({ name: 'Task' })) {
  @resourcefulColumn.integer({
    type: priorityType,
    nullable: false
  })
  declare priority: number

  @resourcefulColumn.integer({
    type: sortOrderType,
    nullable: true
  })
  declare sortOrder: number
}

Time and Duration

typescript
// Duration in seconds
const durationSecondsType = ResourcefulIntegerType({
  minimum: 1,
  maximum: 86400,  // 24 hours in seconds
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

// Duration in minutes
const durationMinutesType = ResourcefulIntegerType({
  minimum: 1,
  maximum: 1440,   // 24 hours in minutes
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

class Meeting extends compose(BaseModel, withResourceful({ name: 'Meeting' })) {
  @resourcefulColumn.integer({
    type: durationMinutesType,
    nullable: false
  })
  declare durationMinutes: number

  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 5,     // Minimum 5-minute intervals
      maximum: 1440,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 5   // Must be in 5-minute increments
    }),
    nullable: true
  })
  declare reminderMinutes: number
}

Advanced Examples

Inventory Management

typescript
class Inventory extends compose(BaseModel, withResourceful({ name: 'Inventory' })) {
  // Current stock level
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 0,
      maximum: 100000,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: false
  })
  declare currentStock: number

  // Minimum stock threshold
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 0,
      maximum: 1000,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: false
  })
  declare minimumStock: number

  // Maximum capacity
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 1,
      maximum: 100000,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: false
  })
  declare maxCapacity: number

  // Reorder quantity
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 1,
      maximum: 10000,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: true
  })
  declare reorderQuantity: number
}

Gaming and Scoring

typescript
class GameScore extends compose(BaseModel, withResourceful({ name: 'GameScore' })) {
  // Player level (1-100)
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 1,
      maximum: 100,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: false
  })
  declare level: number

  // Experience points
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 0,
      maximum: 10000000,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: false
  })
  declare experiencePoints: number

  // High score
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 0,
      maximum: 2147483647,  // Max 32-bit integer
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: true
  })
  declare highScore: number

  // Lives remaining
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 0,
      maximum: 99,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: false
  })
  declare livesRemaining: number
}

Survey and Polling

typescript
class SurveyResponse extends compose(BaseModel, withResourceful({ name: 'SurveyResponse' })) {
  // Likert scale (1-7)
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 1,
      maximum: 7,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: true
  })
  declare satisfactionRating: number

  // NPS score (-100 to +100, but in increments of 10)
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: -100,
      maximum: 100,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 10
    }),
    nullable: true
  })
  declare npsScore: number

  // Multiple choice answer (1-5 options)
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 1,
      maximum: 5,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: true
  })
  declare multipleChoiceAnswer: number
}

Financial and Accounting

typescript
class Transaction extends compose(BaseModel, withResourceful({ name: 'Transaction' })) {
  // Amount in cents to avoid floating point issues
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 1,           // Minimum 1 cent
      maximum: 1000000000,  // Maximum $10M in cents
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: false
  })
  declare amountCents: number

  // Installment number
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 1,
      maximum: 60,  // Maximum 60 installments
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: true
  })
  declare installmentNumber: number

  // Total installments
  @resourcefulColumn.integer({
    type: ResourcefulIntegerType({
      minimum: 1,
      maximum: 60,
      exclusiveMinimum: false,
      exclusiveMaximum: false,
      multipleOf: 1
    }),
    nullable: true
  })
  declare totalInstallments: number
}

Exclusive vs Inclusive Bounds

Understanding the difference between exclusive and inclusive bounds:

typescript
// Age: must be 18 or older (inclusive minimum)
const adultAgeType = ResourcefulIntegerType({
  minimum: 18,              // Can be exactly 18
  maximum: 150,
  exclusiveMinimum: false,  // 18 is allowed
  exclusiveMaximum: false,
  multipleOf: 1
})

// Page number: must be greater than 0 (exclusive minimum)
const pageNumberType = ResourcefulIntegerType({
  minimum: 0,               // Must be > 0 (so minimum is 1)
  maximum: 9999,
  exclusiveMinimum: true,   // 0 is not allowed
  exclusiveMaximum: false,
  multipleOf: 1
})

// Percentage as integer: 0-99 (exclusive maximum)
const percentageType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 100,             // Must be < 100 (so maximum is 99)
  exclusiveMinimum: false,
  exclusiveMaximum: true,   // 100 is not allowed
  multipleOf: 1
})

Multiple Validation Patterns

typescript
// Even numbers only
const evenType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 100,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 2
})

// Multiples of 5 (for ratings out of 100)
const ratingType = ResourcefulIntegerType({
  minimum: 0,
  maximum: 100,
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 5  // 0, 5, 10, 15, 20, ..., 100
})

// Multiples of 10 (for currency in units of 10 cents)
const priceType = ResourcefulIntegerType({
  minimum: 10,    // Minimum $0.10
  maximum: 100000, // Maximum $1000.00
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 10   // In units of 10 cents
})

32-bit Integer Limits

ResourcefulIntegerType is designed for 32-bit signed integers:

typescript
// Maximum safe 32-bit signed integer
const maxIntType = ResourcefulIntegerType({
  minimum: -2147483648,  // -2^31
  maximum: 2147483647,   // 2^31 - 1
  exclusiveMinimum: false,
  exclusiveMaximum: false,
  multipleOf: 1
})

// For larger numbers, use ResourcefulBigintType instead

OpenAPI Schema Generation

ResourcefulIntegerType generates OpenAPI 3.0 schemas with int32 format:

typescript
const integerType = ResourcefulIntegerType({
  minimum: 1,
  maximum: 100,
  exclusiveMinimum: false,
  exclusiveMaximum: true,
  multipleOf: 5
})

// Generated OpenAPI schema:
{
  "type": "integer",
  "format": "int32",
  "minimum": 1,
  "maximum": 100,
  "exclusiveMaximum": true,
  "multipleOf": 5
}

Best Practices

  1. Use appropriate ranges: Set realistic minimum and maximum values for your domain
  2. Consider exclusive bounds: Use when boundary values don't make sense
  3. Handle currency properly: Use integers for currency (store cents, not dollars)
  4. Use multipleOf wisely: Ensure constraints match business requirements
  5. Document units clearly: Make units obvious (seconds, minutes, cents, etc.)
  6. Validate business logic: Ensure ranges make sense in your application context
  7. Consider nullable carefully: Decide if zero vs null has different meanings
  8. Use read-only for IDs: Mark auto-generated integers as read-only
  9. Test edge cases: Verify behavior at boundaries
  10. Consider 64-bit needs: Use ResourcefulBigintType for large numbers

Common Validation Ranges

Age and Demographics

typescript
// Human age: 0-150
{ minimum: 0, maximum: 150 }

// Working age: 16-67
{ minimum: 16, maximum: 67 }

// Adult age: 18+
{ minimum: 18, maximum: 150 }

Ratings and Scores

typescript
// 5-star rating: 1-5
{ minimum: 1, maximum: 5 }

// Percentage: 0-100
{ minimum: 0, maximum: 100 }

// School grade: 0-100
{ minimum: 0, maximum: 100 }

Time and Duration

typescript
// Hour (24-hour format): 0-23
{ minimum: 0, maximum: 23 }

// Minute/Second: 0-59
{ minimum: 0, maximum: 59 }

// Day of month: 1-31
{ minimum: 1, maximum: 31 }

// Month: 1-12
{ minimum: 1, maximum: 12 }

Quantities and Counts

typescript
// Positive count: 0+
{ minimum: 0, maximum: 999999 }

// Required count: 1+
{ minimum: 1, maximum: 999999 }

// Small quantity: 1-99
{ minimum: 1, maximum: 99 }