is-valid-orcid-id.ts
1 /** 2 * Validates an ORCID iD. 3 * 4 * An ORCID iD is a 16-character string that follows a specific structure: 5 * - It consists of 15 digits followed by a check digit (0-9 or 'X'). 6 * - It is often formatted with hyphens, e.g., "0000-0002-1825-0097". 7 * - The validation uses the ISO 7064 11,2 checksum algorithm. 8 * 9 * @param {string} orcid The ORCID iD string to validate. 10 * @returns {boolean} True if the ORCID iD is valid, false otherwise. 11 */ 12 export default function isValidOrcidId(orcidId: string): boolean { 13 if (typeof orcidId !== 'string') { 14 return false; 15 } 16 17 // Remove hyphens and whitespace to get the base 16 characters. 18 const baseStr: string = orcidId.replace(/[-\s]/g, ''); 19 20 // An ORCID must be 16 characters long and match the pattern: 21 // 15 digits followed by a final character that is a digit or 'X'. 22 const orcidPattern: RegExp = /^\d{15}[\dX]$/; 23 if (!orcidPattern.test(baseStr.toUpperCase())) { 24 return false; 25 } 26 27 // --- Checksum Calculation (ISO 7064 11,2) --- 28 29 let total: number = 0; 30 // Iterate over the first 15 digits of the ORCID. 31 for (let i = 0; i < 15; i++) { 32 const digit: number = parseInt(baseStr[i], 10); 33 total = (total + digit) * 2; 34 } 35 36 // Calculate the remainder when divided by 11. 37 const remainder: number = total % 11; 38 // Subtract the remainder from 12. 39 const result: number = (12 - remainder) % 11; 40 41 // Determine the correct check digit from the result. 42 // If the result is 10, the check digit is 'X'. Otherwise, it's the digit itself. 43 const calculatedCheckDigit: string = result === 10 ? 'X' : String(result); 44 45 // Get the actual check digit from the input string. 46 const actualCheckDigit: string = baseStr.charAt(15).toUpperCase(); 47 48 // Compare the calculated check digit with the actual one. 49 return calculatedCheckDigit === actualCheckDigit; 50 }