/** * Validates a NIK (Nomor Induk Kependudukan) format. * * A valid NIK must: * - Be exactly 16 digits * - Have a valid province code (positions 1-2) * - Have a valid date (positions 7-12) * - Not be in the future * - Not be before 1900 * * For female NIKs, the day is encoded as (actual day + 40). * For example, a female born on the 15th would have day = 55. * * @param nik - The 16-digit NIK string to validate * @returns `true` if the NIK is valid, `false` otherwise * * @example * ```typescript * validateNIK('3201234567890123'); // true - valid NIK * validateNIK('1234'); // false - wrong length * validateNIK('9912345678901234'); // false - invalid province * ``` * * @public */ declare function validateNIK(nik: string): boolean; /** * Information extracted from a valid NIK. * * Contains parsed data including location codes, birth date, gender, * and serial number from a 16-digit NIK string. * * @public */ interface NIKInfo { /** * Province information extracted from positions 1-2 of the NIK. * * @example * ```typescript * { code: '32', name: 'Jawa Barat' } * ``` */ province: { /** Two-digit province code (e.g., '32') */ code: string; /** Full province name (e.g., 'Jawa Barat') */ name: string; }; /** * Regency (Kabupaten/Kota) information extracted from positions 3-4 of the NIK. * * @example * ```typescript * { code: '01', name: 'Kab. Bogor' } * ``` */ regency: { /** Two-digit regency code (e.g., '01') */ code: string; /** Full regency name (e.g., 'Kab. Bogor') */ name: string; }; /** * District (Kecamatan) information extracted from positions 5-6 of the NIK. * May be `null` if district data is not available. * * @example * ```typescript * { code: '23', name: 'Ciawi' } * ``` */ district: { /** Two-digit district code (e.g., '23') */ code: string; /** Full district name, or `null` if data unavailable */ name: string | null; }; /** * Birth date extracted from positions 7-12 of the NIK. * For females, the day is encoded as (actual day + 40). * Returns `null` if the date is invalid. * * @example * ```typescript * new Date(1989, 0, 31) // January 31, 1989 * ``` */ birthDate: Date | null; /** * Gender derived from the day encoding in the NIK. * - 'male': day is 1-31 * - 'female': day is 41-71 (actual day + 40) * - `null`: if unable to determine */ gender: 'male' | 'female' | null; /** * Serial number from positions 13-16 of the NIK. * Uniquely identifies individuals with the same location and birth date. * Returns `null` if unable to extract. * * @example * ```typescript * '0123' * ``` */ serialNumber: string | null; /** * Whether the NIK passed validation checks. * If `false`, other fields may be `null` or contain partial data. */ isValid: boolean; } /** * Options for masking a NIK to protect privacy. * * Controls how many characters to show at the start and end, * what character to use for masking, and optional separators. * * @example * Default masking: * ```typescript * { visibleStart: 4, visibleEnd: 4, maskChar: '*' } * // Result: '3201********0123' * * // With separator * { visibleStart: 4, visibleEnd: 4, maskChar: '*', separator: '-' } * // Result: '3201-****-****-0123' * ``` * * @public */ interface MaskOptions { /** * Number of characters to show at the start. * * @defaultValue 4 */ visibleStart?: number; /** * Number of characters to show at the end. * * @defaultValue 4 */ visibleEnd?: number; /** * Character to use for masking hidden digits. * * @defaultValue '*' */ maskChar?: string; /** * Optional separator to add between groups of digits. * If provided, the NIK will be formatted with separators. * * @defaultValue undefined (no separator) * * @example * ```typescript * '-' // Results in format: '3201-****-****-0123' * ' ' // Results in format: '3201 **** **** 0123' * ``` */ separator?: string; /** * @deprecated Use `visibleStart` instead. Deprecated in v0.7.0. */ start?: number; /** * @deprecated Use `visibleEnd` instead. Deprecated in v0.7.0. */ end?: number; /** * @deprecated Use `maskChar` instead. Deprecated in v0.7.0. */ char?: string; } /** * Error thrown when an invalid NIK is provided to a function. * Extends native Error with a `code` property for programmatic error handling. * * @example * ```typescript * try { * requireNIK('invalid'); * } catch (error) { * if (error instanceof InvalidNIKError) { * console.log(error.code); // 'INVALID_NIK' * } * } * ``` * * @public */ declare class InvalidNIKError extends Error { /** Error code for programmatic identification */ readonly code: "INVALID_NIK"; constructor(message?: string); } /** * Error codes for detailed NIK validation. * * @public */ type NIKErrorCode = 'INVALID_FORMAT' | 'INVALID_PROVINCE' | 'INVALID_MONTH' | 'INVALID_DAY' | 'INVALID_DATE' | 'FUTURE_DATE'; /** * A single validation error with code and message. * * @public */ interface NIKValidationError { /** Error code for programmatic handling */ code: NIKErrorCode; /** Human-readable error message */ message: string; } /** * Detailed validation result for NIK with structured error reporting. * * Use this for form validation where you need to show specific error * messages per field. * * @example * ```typescript * const result = validateNIKDetailed('1234'); * if (!result.isValid) { * result.errors.forEach(err => { * console.log(err.code, err.message); * }); * } * ``` * * @public */ interface NIKValidationResult { /** Whether the NIK is valid */ isValid: boolean; /** List of validation errors (empty if valid) */ errors: NIKValidationError[]; /** Cleaned 16-digit NIK if valid, null otherwise */ nik: string | null; } /** * Options for getAge function. * * @public */ interface GetAgeOptions { /** Date to calculate age from (default: current date) */ referenceDate?: Date; /** Return formatted Indonesian string instead of object */ asString?: boolean; } /** * Age result object with years, months, and days. * * @public */ interface Age { /** Full years */ years: number; /** Remaining months after full years */ months: number; /** Remaining days after full months */ days: number; } /** * Parses a NIK and extracts all embedded information. * * Extracts province, regency, district codes, birth date, gender, * and serial number from a 16-digit NIK string. * * @param nik - The 16-digit NIK string to parse * @returns Parsed NIK information, or `null` if the NIK format is invalid * * @example * Parse a valid male NIK: * ```typescript * const info = parseNIK('3201018901310123'); * console.log(info); * // { * // province: { code: '32', name: 'Jawa Barat' }, * // regency: { code: '01', name: 'Kab. Bogor' }, * // district: { code: '01', name: null }, * // birthDate: Date(1989, 0, 31), // Jan 31, 1989 * // gender: 'male', * // serialNumber: '0123', * // isValid: true * // } * ``` * * @example * Parse a female NIK (day + 40): * ```typescript * const info = parseNIK('3201019508550123'); * console.log(info.gender); // 'female' * console.log(info.birthDate); // Date(1995, 7, 15) - Aug 15, 1995 * ``` * * @example * Invalid NIK returns null: * ```typescript * const info = parseNIK('invalid'); * console.log(info); // null * ``` * * @public */ declare function parseNIK(nik: string): NIKInfo | null; /** * Formats a NIK with separators for better readability. * * Groups the NIK into logical segments: province, regency, district, * year, month, day, and serial number. * * @param nik - The 16-digit NIK string to format * @param separator - Character to use as separator * @returns Formatted NIK string, or original string if invalid format * * @example * Default separator (dash): * ```typescript * formatNIK('3201234567890123'); * // '32-01-23-45-67-89-0123' * ``` * * @example * Custom separator: * ```typescript * formatNIK('3201234567890123', ' '); * // '32 01 23 45 67 89 0123' * ``` * * @example * Invalid NIK returns as-is: * ```typescript * formatNIK('1234'); * // '1234' * ``` * * @public */ declare function formatNIK(nik: string, separator?: string): string; /** * Masks a NIK to protect privacy while keeping partial visibility. * * By default, shows the first 4 and last 4 digits, masking the middle 8. * Optionally formats the masked NIK with separators. * * @param nik - The 16-digit NIK string to mask * @param options - Masking configuration options * @returns Masked NIK string, or original string if invalid format * * @example * Default masking (first 4, last 4): * ```typescript * maskNIK('3201234567890123'); * // '3201********0123' * ``` * * @example * Custom mask character: * ```typescript * maskNIK('3201234567890123', { maskChar: 'X' }); * // '3201XXXXXXXX0123' * ``` * * @example * With separator: * ```typescript * maskNIK('3201234567890123', { separator: '-' }); * // '32-01-**-**-**-**-0123' * ``` * * @example * Custom visibleStart and visibleEnd: * ```typescript * maskNIK('3201234567890123', { visibleStart: 6, visibleEnd: 4 }); * // '320123******0123' * ``` * * @public */ declare function maskNIK(nik: string, options?: MaskOptions): string; /** * Cleans a NIK by removing all non-digit characters. * * Accepts NIK in any format (with separators like `.`, `-`, ` `) and * returns a clean 16-digit string. Returns empty string for invalid inputs. * * @param nik - NIK in any format * @returns Clean 16-digit NIK or empty string if invalid * * @example * ```typescript * cleanNIK('32-01-01-89-01-31-0123'); // '3201018901310123' * cleanNIK('3201.8901.3101.23'); // '32018901310123' (only 14 digits - invalid) * cleanNIK('invalid'); // '' * ``` * * @public */ declare function cleanNIK(nik: string): string; /** * Validates a NIK and returns detailed error information. * * Unlike `validateNIK` which returns a boolean, this function provides * structured error reporting for form validation use cases. * * @param nik - The NIK string to validate (accepts any format with separators) * @returns Detailed validation result with errors array * * @example * ```typescript * const result = validateNIKDetailed('3201018901310123'); * if (!result.isValid) { * result.errors.forEach(err => { * console.log(`${err.code}: ${err.message}`); * }); * } * ``` * * @public */ declare function validateNIKDetailed(nik: string): NIKValidationResult; /** * Calculates the age of a person based on their NIK. * * Returns detailed age breakdown with years, months, and days, or a * formatted Indonesian string. This is consistent with `datetime.getAge()`. * * @param nik - The 16-digit NIK string * @param options - Options object with `referenceDate` and `asString` * @returns Age object `{ years, months, days }`, formatted string, or null if invalid * * @example * ```typescript * // Returns object by default * getAge('3201018901310123'); * // { years: 35, months: 2, days: 6 } (as of 2026-04-06) * * // Returns formatted string * getAge('3201018901310123', { asString: true }); * // '35 Tahun 2 Bulan 6 Hari' * * // Custom reference date * getAge('3201018901310123', { referenceDate: new Date('2025-01-01') }); * // { years: 35, months: 11, days: 1 } * ``` * * @public */ declare function getAge(nik: string, options?: GetAgeOptions): Age | string | null; /** * Compares two NIKs to check if they belong to the same person. * * Two NIKs are considered the same person if they have identical: * - Province code (positions 1-2) * - Regency code (positions 3-4) * - District code (positions 5-6) * - Birth date (year + month + day) * - Gender (derived from day encoding) * - Serial number (positions 13-16) * * @param nik1 - First NIK (accepts any format) * @param nik2 - Second NIK (accepts any format) * @returns True if both NIKs belong to the same person, false otherwise * * @example * ```typescript * // Same person, same format * compareNIK('3201018901310123', '3201018901310123'); // true * * // Same person, different format * compareNIK('3201018901310123', '3201-01-89-01-31-0123'); // true * * // Different serial number * compareNIK('3201018901310123', '3201018901310124'); // false * * // Invalid NIK * compareNIK('invalid', '3201018901310123'); // false * ``` * * @public */ declare function compareNIK(nik1: string, nik2: string): boolean; /** * Checks if a person is an adult based on their NIK. * * By default, uses 17 years as the threshold (Indonesian KTP eligibility age). * Indonesian law allows KTP at age 17, or upon marriage, or already married. * * @param nik - The 16-digit NIK string * @param minAge - Minimum age threshold (default: 17) * @returns True if the person is at least minAge years old, false otherwise * * @example * ```typescript * // Born 1995-01-01, reference 2026-04-06 (age 31) * isAdult('3201950101950123'); // true (31 >= 17) * isAdult('3201950101950123', 21); // true (31 >= 21) * * // Born 2010-01-01, reference 2026-04-06 (age 16) * isAdult('3210010101950123'); // false (16 < 17) * isAdult('3210010101950123', 16); // true (16 >= 16) * * // Invalid NIK * isAdult('invalid'); // false * ``` * * @public */ declare function isAdult(nik: string, minAge?: number): boolean; /** * Formats the birth date from a NIK into a human-readable string. * * @param nik - The 16-digit NIK string * @param locale - The locale to use for formatting (default: 'id-ID') * @returns Formatted birth date string, or null if invalid * * @example * ```typescript * formatBirthDate('3201018901310123'); // '31 Januari 1989' * ``` */ declare function formatBirthDate(nik: string): string | null; /** * Checks if a NIK matches a specific gender. * * @param nik - The 16-digit NIK string * @param gender - The gender to check ('male' | 'female') * @returns True if the NIK matches the gender, false otherwise */ declare function isValidForGender(nik: string, gender: 'male' | 'female'): boolean; /** * Checks if a NIK matches a specific birth date. * * @param nik - The 16-digit NIK string * @param birthDate - The birth date to check * @returns True if the NIK matches the birth date, false otherwise */ declare function isValidForBirthDate(nik: string, birthDate: Date): boolean; export { type Age, type GetAgeOptions, InvalidNIKError, type MaskOptions, type NIKErrorCode, type NIKInfo, type NIKValidationError, type NIKValidationResult, cleanNIK, compareNIK, formatBirthDate, formatNIK, getAge, isAdult, isValidForBirthDate, isValidForGender, maskNIK, parseNIK, validateNIK, validateNIKDetailed };