Brazilian CPF
class CPF {
private value: string;
constructor(cpf: string) {
if (!this.validateCPF(cpf)) {
throw new Error("Invalid CPF. Please provide a valid CPF number.");
}
this.value = cpf;
}
equals(other: CPF): boolean {
return this.value === other.value;
}
toString(): string {
return this.value;
}
private validateCPF(cpf: string): boolean {
// Remove non-numeric characters and check if the length is valid
cpf = cpf.replace(/\D/g, "");
if (cpf.length !== 11) {
return false;
}
// Check for known invalid CPFs
const invalidCPFs = [
"00000000000",
"11111111111",
"22222222222",
"33333333333",
"44444444444",
"55555555555",
"66666666666",
"77777777777",
"88888888888",
"99999999999",
];
if (invalidCPFs.includes(cpf)) {
return false;
}
// Calculate and verify the CPF checksum
const numbers = cpf.substring(0, 9).split("").map(Number);
const checksum1 =
numbers.reduce((sum, value, index) => sum + value * (10 - index), 0) % 11;
const checksum2 =
numbers.reduce((sum, value, index) => sum + value * (11 - index), 0) % 11;
const validChecksum1 = checksum1 < 2 ? 0 : 11 - checksum1;
const validChecksum2 = checksum2 < 2 ? 0 : 11 - checksum2;
return numbers[9] === validChecksum1 && numbers[10] === validChecksum2;
}
}
// Example usage:
const validCPF = new CPF("123.456.789-09"); // A valid CPF
const invalidCPF = new CPF("123.456.789-00"); // An invalid CPF
console.log(validCPF.toString()); // Output: "12345678909"
console.log(invalidCPF.toString()); // Throws an error for an invalid CPF
Specs
import { CPF } from "./cpf"; // Import the CPF class
describe("CPF", () => {
describe("constructor", () => {
it("should create a CPF instance with a valid CPF number", () => {
const cpf = new CPF("123.456.789-09");
expect(cpf).toBeDefined();
});
it("should throw an error for an invalid CPF number", () => {
expect(() => new CPF("123.456.789-00")).toThrow();
expect(() => new CPF("invalid_cpf")).toThrow();
});
});
describe("equals", () => {
it("should return true when comparing two CPF instances with the same CPF number", () => {
const cpf1 = new CPF("123.456.789-09");
const cpf2 = new CPF("12345678909");
expect(cpf1.equals(cpf2)).toBe(true);
});
it("should return false when comparing two CPF instances with different CPF numbers", () => {
const cpf1 = new CPF("123.456.789-09");
const cpf2 = new CPF("987.654.321-09");
expect(cpf1.equals(cpf2)).toBe(false);
});
});
describe("toString", () => {
it("should return the string representation of the CPF", () => {
const cpf = new CPF("123.456.789-09");
expect(cpf.toString()).toBe("12345678909");
});
});
});