@maistik/validate-nif

June 14, 2026 · View on GitHub

CI npm version license

Zero-dependency, isomorphic (Node.js & browser) validator for Spanish fiscal identifiers, written in TypeScript with full type definitions included.

  • DNI / NIF — natural persons, residents (12345678Z)
  • NIE — natural persons, foreigners (X1234567L)
  • CIF — legal entities / organizations (A58818501)
  • 🧮 Official AEAT control-character algorithms
  • 🪶 No dependencies, tree-shakeable, ESM + CommonJS builds
  • 🛡️ Never throws — any input (including null/undefined/numbers) is handled
  • 🧪 100% test coverage

Installation

# npm
npm install @maistik/validate-nif

# pnpm
pnpm add @maistik/validate-nif

# yarn
yarn add @maistik/validate-nif

Usage

ESM / TypeScript

import { isValid, isValidDNI, isValidNIE, isValidCIF, getType } from '@maistik/validate-nif'

isValidDNI('12345678Z')   // true
isValidNIE('X1234567L')   // true
isValidCIF('A58818501')   // true

isValid('12345678Z')      // true (any supported type)
getType('X1234567L')      // 'NIE'

// Loosely formatted input is normalized automatically.
isValid(' 12.345.678-z ') // true

CommonJS

const { validateNif, isValid } = require('@maistik/validate-nif')

isValid('A58818501') // true

Browser

The package ships an ESM build with no Node.js dependencies, so it works directly in the browser via any bundler (Vite, webpack, Rollup, esbuild) or straight from a CDN:

<script type="module">
  import { isValid } from 'https://esm.sh/@maistik/validate-nif'
  console.log(isValid('12345678Z')) // true
</script>

API

All functions accept unknown input and never throw.

FunctionReturnsDescription
isValid(value)booleantrue for a valid DNI, NIE or CIF.
isValidNIF(value)booleantrue for a valid DNI or NIE (natural person).
isValidDNI(value)booleantrue for a valid DNI / NIF.
isValidNIE(value)booleantrue for a valid NIE.
isValidCIF(value)booleantrue for a valid CIF.
getType(value)'DNI' | 'NIE' | 'CIF' | nullThe detected type, or null if invalid.
getCifOrganizationType(value){ code, description } | nullThe organization type for a valid CIF, or null.
parse(value)NifInfoStructured info: { valid, type, normalized, organization }.
format(value, options?)stringCanonical form; options.separator inserts a separator before the control char.
normalize(value)stringUpper-cases and strips spaces, dots, hyphens and underscores.
controlLetterFor(num)stringThe DNI/NIE control letter for an 8-digit number.
validateNif(value)numberLegacy numeric code (see below).

Parsing & organization types

import { parse, getCifOrganizationType, format } from '@maistik/validate-nif'

parse('a-58818501')
// {
//   valid: true,
//   type: 'CIF',
//   normalized: 'A58818501',
//   organization: { code: 'A', description: 'Sociedad anónima' },
// }

getCifOrganizationType('G12345678') // { code: 'G', description: 'Asociación o fundación' }

format('12345678z', { separator: '-' }) // '12345678-Z'

A CIF's leading letter is mapped to its Spanish organization type (Sociedad anónima, Sociedad de responsabilidad limitada, Cooperativa, Asociación, Corporación local, and so on — the full AEAT set is supported).

validateNif result codes

validateNif is kept for backwards compatibility. It returns a numeric code: negative means invalid, >= 0 means valid.

CodeConstantMeaning
-1ValidationResult.ERRORInvalid / unknown value
1ValidationResult.DNIValid DNI / NIF
4ValidationResult.NIEValid NIE
20ValidationResult.CIFValid CIF
import { validateNif, ValidationResult } from '@maistik/validate-nif'

validateNif('62805436A') // 1  (>= 0 → valid)
validateNif('62805436X') // -1 (< 0 → invalid)
validateNif('A58818501') === ValidationResult.CIF // true

Types

Type declarations (.d.ts) are bundled and exposed automatically — no @types/* package is required. The package also exports the NifType, NifInfo, CifOrganizationType, FormatOptions and ValidationResultCode helper types.

Development

pnpm install
pnpm test:coverage   # tests with 100% coverage enforcement
pnpm lint            # eslint
pnpm typecheck       # tsc --noEmit
pnpm build           # build dist/ (ESM + CJS + .d.ts)

See CONTRIBUTING.md for the full contribution guide.

License

MIT © Maistik Studio