A lightweight, fast, and comprehensive npm package for validating UK National Insurance Numbers (NINO) with full compliance to HMRC rules.
- ✅ Complete HMRC compliance - Validates against all official NINO rules
- 🚀 Blazing fast - 5M+ ops/sec, zero dependencies, all functions rated "Excellent"
- 🛡️ Type safe - Full JSDoc documentation with TypeScript-friendly types
- 🔧 Flexible options - Configurable validation behavior
- 🎯 100% test coverage - Thoroughly tested with comprehensive test suite
- 📱 Cross-platform - Works in Node.js and browsers
- 📦 Dual package - Supports both CommonJS and ES Modules (ESM)
- 🏷️ TypeScript ready - Includes TypeScript declaration files
npm install nino-validator
const { validateNINO } = require('nino-validator');
// Simple validation
console.log(validateNINO('AB123456C')); // true
console.log(validateNINO('invalid')); // false
import { validateNINO } from 'nino-validator';
// Simple validation
console.log(validateNINO('AB123456C')); // true
console.log(validateNINO('invalid')); // false
import { validateNINO, ValidationOptions } from 'nino-validator';
const options: ValidationOptions = { requireSuffix: true };
const isValid: boolean = validateNINO('AB123456C', options);
CommonJS:
const { validateNINO, formatNINO, parseNINO, generateRandomNINO } = require('nino-validator');
ES Modules:
import { validateNINO, formatNINO, parseNINO, generateRandomNINO } from 'nino-validator';
Usage (same for both formats):
// Validate different NINO formats
validateNINO('AB123456C'); // true - standard format
validateNINO('AB123456'); // true - suffix optional by default
validateNINO('ab123456c'); // true - case insensitive
validateNINO('AB 12 34 56 C'); // true - spaces allowed by default
validateNINO(' AB123456C '); // true - whitespace trimmed
validateNINO('invalid-nino'); // false - invalid format
// Require suffix letter
validateNINO('AB123456', { requireSuffix: true }); // false - no suffix
validateNINO('AB123456C', { requireSuffix: true }); // true - has suffix
// Strict formatting (no spaces allowed)
validateNINO('AB 12 34 56 C', { allowSpaces: false }); // false - contains spaces
validateNINO('AB123456C', { allowSpaces: false }); // true - no spaces
// Combine options
validateNINO('AB123456C', {
requireSuffix: true,
allowSpaces: false
}); // true
// Standard formatting with spaces
formatNINO('AB123456C'); // 'AB 12 34 56 C'
formatNINO('ab123456c'); // 'AB 12 34 56 C' (normalized)
formatNINO('AB123456'); // 'AB 12 34 56' (no suffix)
formatNINO('invalid'); // null (invalid NINO)
// Clean up user input
const userInput = ' ab 12 34 56 c ';
const formatted = formatNINO(userInput); // 'AB 12 34 56 C'
// Extract all components
const result = parseNINO('AB123456C');
console.log(result);
// Output:
// {
// prefix: 'AB',
// numbers: '123456',
// suffix: 'C',
// formatted: 'AB 12 34 56 C',
// original: 'AB123456C'
// }
// Handle NINOs without suffix
const noSuffix = parseNINO('AB123456');
console.log(noSuffix.suffix); // null
// Invalid NINOs return null
parseNINO('invalid'); // null
// Generate random valid NINOs for testing
const testNINO = generateRandomNINO();
console.log(testNINO); // e.g., 'JG123789A'
console.log(validateNINO(testNINO)); // always true
// Generate multiple test cases
const testCases = Array.from({ length: 10 }, () => generateRandomNINO());
console.log(testCases);
// ['AB123456C', 'JK789012G', 'MN345678P', ...]
Validates a UK National Insurance Number against HMRC rules.
Parameters:
nino
(string): The NINO to validateoptions
(object, optional):allowSpaces
(boolean, default:true
): Allow spaces in the inputrequireSuffix
(boolean, default:false
): Require the suffix letter
Returns: boolean
- true
if valid, false
otherwise
Example:
validateNINO('AB123456C'); // true
validateNINO('AB123456', { requireSuffix: true }); // false
Formats a NINO with standard UK government spacing (XX ## ## ## X).
Parameters:
nino
(string): The NINO to format
Returns: string | null
- Formatted NINO or null
if invalid
Example:
formatNINO('AB123456C'); // 'AB 12 34 56 C'
formatNINO('invalid'); // null
Extracts and validates components from a NINO.
Parameters:
nino
(string): The NINO to parse
Returns: object | null
- Components object or null
if invalid
Return object structure:
{
prefix: string; // Two-letter prefix (e.g., 'AB')
numbers: string; // Six-digit number (e.g., '123456')
suffix: string | null; // Single suffix letter or null
formatted: string; // Standardized format
original: string; // Original input
}
Generates a random valid NINO for testing purposes.
Returns: string
- A randomly generated valid NINO
Example:
const testNINO = generateRandomNINO(); // 'JK789012M'
Provides detailed validation with localized error messages.
Parameters:
nino
(string): The NINO to validateoptions
(object, optional): Same asvalidateNINO()
Returns: ValidationResult
- Detailed validation result
Return object structure:
{
isValid: boolean;
error: string | null; // Localized error message
errorCode: string | null; // Machine-readable error code
suggestion: string | null; // Localized suggestion
}
Example:
const result = validateNINOWithDetails('AB123');
console.log(result);
// {
// isValid: false,
// error: 'NINO too short (5 characters). Minimum 8 characters required',
// errorCode: 'TOO_SHORT',
// suggestion: 'Ensure the NINO has 2 letters, 6 digits, and optionally 1 letter'
// }
The NINO Validator supports multiple languages for error messages. Currently supported languages are English (en
) and Greek (el
).
const {
setLanguage,
getCurrentLanguage,
getSupportedLanguages,
isLanguageSupported
} = require('nino-validator');
// Check supported languages
console.log(getSupportedLanguages());
// { en: 'English', el: 'Ελληνικά (Greek)' }
// Switch to Greek
setLanguage('el');
console.log(getCurrentLanguage()); // 'el'
// Validate with Greek error messages
const result = validateNINOWithDetails('invalid');
console.log(result.error);
// 'Μη έγκυρη μορφή NINO. Αναμενόμενη μορφή: XX123456X (το επίθημα είναι προαιρετικό)'
// Switch back to English
setLanguage('en');
const { detectLanguage, initializeI18n } = require('nino-validator');
// Auto-detect language from environment
const detected = detectLanguage();
console.log(detected); // 'el' if Greek locale detected
// Initialize with auto-detection
const language = initializeI18n({ autoDetect: true });
console.log(`Language set to: ${language}`);
// Initialize with fallback
initializeI18n({
autoDetect: true,
fallbackLanguage: 'el'
});
- Consistent Error Codes: Error codes remain the same across languages for programmatic handling
- Parameter Interpolation: Dynamic values (like lengths, invalid characters) are properly inserted into translated messages
- Environment Detection: Automatically detects language from Node.js environment variables or browser settings
- Fallback Handling: Gracefully falls back to English if requested language is not supported
To add support for additional languages, error messages need to be translated in the internal message files. Contact the maintainer for language addition requests.
This package validates against all official HMRC rules:
- Structure: Two letters + Six digits + One optional letter
- Example:
AB123456C
orAB123456
- Invalid Prefixes: BG, GB, NK, KN, TN, NT, ZZ, and all combinations starting with D, F, G, I, N, O, Q, U, V
- Invalid First Letters: D, F, I, Q, U, V
- Invalid Second Letters: D, F, I, Q, U, V
- Invalid Suffixes: D, F, I, Q, U, V
- Repeated Numbers: All six digits cannot be identical (e.g., 111111)
// ✅ Valid NINOs
'AB123456C' // Standard format
'AB123456' // Without suffix
'JG103759A' // Real-world example
'AB 12 34 56 C' // With spaces
// ❌ Invalid NINOs
'BG123456C' // Invalid prefix 'BG'
'AB111111C' // All digits the same
'AB123456D' // Invalid suffix 'D'
'DA123456C' // Invalid first letter 'D'
'AB12345' // Too few digits
'A1234567' // Wrong format
The package handles errors gracefully:
// Type safety
validateNINO(null); // false
validateNINO(undefined); // false
validateNINO(123456789); // false
validateNINO(''); // false
// Invalid formats return null
formatNINO('invalid'); // null
parseNINO('invalid'); // null
// Options validation
validateNINO('AB123456C', { invalidOption: true }); // Works (ignores invalid options)
NINO Validator is designed for high performance with comprehensive benchmarking:
- Zero dependencies - No external packages required
- Fast validation - Optimized regex and lookup operations
- Memory efficient - Minimal memory footprint
- Browser compatible - Works in all modern browsers
Run comprehensive performance tests:
# Full benchmark suite with detailed analysis
npm run benchmark
# Quick CI-friendly performance check
npm run benchmark:ci
# Memory-focused benchmarks with GC control
npm run benchmark:memory
Sample Benchmark Output:
⚡ NINO Validator CI Benchmarks
===============================
✅ validateNINO (valid) | 2,350,000 ops/sec | 0.4μs/op
✅ validateNINO (invalid) | 5,150,000 ops/sec | 0.2μs/op
✅ formatNINO | 915,000 ops/sec | 1.1μs/op
✅ parseNINO | 800,000 ops/sec | 1.2μs/op
✅ generateRandomNINO | 575,000 ops/sec | 1.7μs/op
✅ Bulk validation | 3,000,000 ops/sec | 0.3μs/op
🎯 Performance check: ✅ PASS
On modern hardware (Node.js v18+):
Function | Operations/Second | Rating | Use Case |
---|---|---|---|
validateNINO (valid) |
2,350,000+ | 🟢 Excellent | Form validation |
validateNINO (invalid) |
5,150,000+ | 🟢 Excellent | Input filtering |
formatNINO |
915,000+ | 🟢 Excellent | Display formatting |
parseNINO |
800,000+ | 🟢 Excellent | Data extraction |
generateRandomNINO |
575,000+ | 🟢 Excellent | Test data generation |
Bulk validation | 3,000,000+ | 🟢 Excellent | Batch processing |
Rating | Operations/Second | Description |
---|---|---|
🟢 Excellent | ≥100,000 | Outstanding performance |
🟡 Good | ≥10,000 | Acceptable performance |
🔴 Poor | <10,000 | May need optimization |
Performance Insights:
- Invalid inputs are validated ~2x faster than valid ones (short-circuit validation)
- Bulk operations can process over 3 million NINOs per second
- Memory usage is minimal (~0.1MB for 10,000 operations)
- All functions consistently achieve "Excellent" performance ratings
- Zero performance degradation with large datasets
See benchmark documentation for detailed performance analysis and optimization tips.
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/nino-validator@latest/index.js"></script>
</head>
<body>
<script>
// Use the global ninoValidator object
console.log(ninoValidator.validateNINO('AB123456C')); // true
</script>
</body>
</html>
While this package is written in JavaScript, it includes comprehensive JSDoc comments for TypeScript IntelliSense:
import { validateNINO, formatNINO, parseNINO, generateRandomNINO } from 'nino-validator';
const isValid: boolean = validateNINO('AB123456C');
const formatted: string | null = formatNINO('AB123456C');
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run linting
npm run lint
function validateNINOInput(input) {
const nino = input.trim();
if (!nino) {
return { valid: false, error: 'NINO is required' };
}
if (!validateNINO(nino)) {
return { valid: false, error: 'Invalid NINO format' };
}
return { valid: true, formatted: formatNINO(nino) };
}
// Usage
const result = validateNINOInput(' ab 12 34 56 c ');
console.log(result); // { valid: true, formatted: 'AB 12 34 56 C' }
function normalizeNINO(input) {
const parsed = parseNINO(input);
if (!parsed) return null;
return {
prefix: parsed.prefix,
numbers: parsed.numbers,
suffix: parsed.suffix,
display: parsed.formatted
};
}
function createTestUser() {
return {
id: Math.random().toString(36),
nino: generateRandomNINO(),
name: 'Test User'
};
}
See CHANGELOG.md for version history.
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Make your changes
- Add tests for new functionality
- Ensure all tests pass (
npm test
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
git clone https://github.com/icodenet/nino-validator.git
cd nino-validator
npm install
npm test
MIT © Byron Thanopoulos
- 📧 Email: byron.thanopoulos@gmail.com
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions