south-african-id-validator
Version:
Validate South African ID numbers and extract date of birth, gender, and citizenship. TypeScript-native, zero dependencies, runs anywhere.
77 lines • 2.7 kB
text/typescript
//#region src/types.d.ts
/**
* The gender encoded in a South African ID number.
*/
type Gender = "male" | "female";
/**
* The citizenship status encoded in a South African ID number.
*/
type Citizenship = "citizen" | "permanent_resident";
/**
* The reason a South African ID number failed validation.
*
* - `INVALID_LENGTH` — the input is not exactly 13 characters.
* - `INVALID_FORMAT` — the input contains non-digit characters, or the
* citizenship digit is neither `0` nor `1`.
* - `INVALID_CHECKSUM` — the digits form a 13-character numeric string but the
* final digit does not match the Luhn checksum of the preceding 12.
* - `INVALID_DATE` — the first six digits do not form a real calendar date
* (e.g. Feb 30, Feb 29 of a non-leap year).
*/
type ValidationErrorCode = "INVALID_LENGTH" | "INVALID_FORMAT" | "INVALID_CHECKSUM" | "INVALID_DATE";
/**
* The result of validating a South African ID number.
*
* Discriminated on `valid`: narrow with `if (result.valid)` to access
* `dateOfBirth`, `gender`, and `citizenship`; narrow with `if (!result.valid)`
* to access `error`.
*/
type ValidationResult = {
valid: true;
dateOfBirth: Date;
gender: Gender;
citizenship: Citizenship;
} | {
valid: false;
error: ValidationErrorCode;
};
/**
* Optional configuration for {@link validate}.
*/
type ValidateOptions = {
/**
* The date used as "today" when inferring the century of the encoded year.
* Inject a fixed value for deterministic tests. Defaults to `new Date()`.
*/
referenceDate?: Date;
};
//#endregion
//#region src/validate.d.ts
/**
* Validate a South African ID number and, on success, extract the encoded
* date of birth, gender, and citizenship.
*
* The result is a discriminated union — narrow with `result.valid` to access
* the data fields, or with `!result.valid` to access the typed `error` code.
*
* The pipeline short-circuits on the first failure and reports the most
* fundamental problem first: length, then character class, then Luhn
* checksum, then date validity, then citizenship digit.
*
* @example
* ```ts
* const result = validate('7311190013080');
* if (result.valid) {
* console.log(result.dateOfBirth, result.gender, result.citizenship);
* } else {
* console.error(result.error);
* }
* ```
*
* @param idNumber The 13-digit ID number to validate.
* @param options Optional overrides — see {@link ValidateOptions}.
*/
declare function validate(idNumber: string, options?: ValidateOptions): ValidationResult;
//#endregion
export { type Citizenship, type Gender, type ValidateOptions, type ValidationErrorCode, type ValidationResult, validate };
//# sourceMappingURL=index.d.mts.map