{"id":18369170,"url":"https://github.com/ideal-postcodes/postcode","last_synced_at":"2025-04-09T13:10:24.740Z","repository":{"id":13099374,"uuid":"15780811","full_name":"ideal-postcodes/postcode","owner":"ideal-postcodes","description":"UK Postcode parsing and helper methods","archived":false,"fork":false,"pushed_at":"2024-02-16T10:18:10.000Z","size":7208,"stargazers_count":70,"open_issues_count":1,"forks_count":7,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-02T12:12:36.571Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://postcodejs.ideal-postcodes.dev/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ideal-postcodes.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-01-09T21:55:48.000Z","updated_at":"2024-11-05T22:03:39.000Z","dependencies_parsed_at":"2024-06-18T15:37:41.939Z","dependency_job_id":"3b1e68c7-524a-4afe-9fab-ec23c9c8b7e8","html_url":"https://github.com/ideal-postcodes/postcode","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ideal-postcodes%2Fpostcode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ideal-postcodes%2Fpostcode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ideal-postcodes%2Fpostcode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ideal-postcodes%2Fpostcode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ideal-postcodes","download_url":"https://codeload.github.com/ideal-postcodes/postcode/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248045245,"owners_count":21038554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T23:28:38.665Z","updated_at":"2025-04-09T13:10:24.710Z","avatar_url":"https://github.com/ideal-postcodes.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg src=\"https://img.ideal-postcodes.co.uk/Postcode.js%20Logo@3x.png\" alt=\"Postcode.js\"\u003e\n\u003c/h1\u003e\n\n\u003e Validate \u0026 parse UK postcodes\n\n[![Size](https://img.shields.io/bundlephobia/minzip/postcode.svg?style=flat)](https://bundlephobia.com/result?p=postcode)\n[![Downloads](https://img.shields.io/npm/dm/postcode.svg)](https://www.npmjs.com/package/postcode)\n[![Try postcode on RunKit](https://badge.runkitcdn.com/postcode.svg)](https://npm.runkit.com/postcode)\n\nUtility methods for UK Postcodes, including validating the shape of a postcode, extracting postcode elements (like incodes, outcodes, areas and [more](#definitions)).\n\nTested against ~1.7 million postcodes on ONSPD.\n\n## Features\n\n- [Check](#validate) whether a postcode conforms to the [correct format](https://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom#Formatting)\n- Single purpose static methods\n- Tested against a list of ~1.7 million postcodes listed on ONS Postcode Directory\n- [Extract](#parse) useful elements of a postcode like incode, outcode, sector\n- Tree-shakeable\n![Postcode Components](https://img.ideal-postcodes.co.uk/uk-postcode-components.gif)\n\n## Links\n\n- [GitHub Repository](https://github.com/ideal-postcodes/postcode)\n- [API Documentation](https://postcodejs.ideal-postcodes.dev)\n- [Try postcode.js on RunKit](https://npm.runkit.com/postcode)\n- [Postcode element definitions](#definitions)\n- [Notes](#notes)\n- [NPM Package](https://www.npmjs.com/package/postcode)\n\n## Guides\n\n- [UK Postcode Format](https://ideal-postcodes.co.uk/guides/uk-postcode-format). An overview of the UK postcode format and its constituent parts\n- [Postcode Validation](https://ideal-postcodes.co.uk/guides/postcode-validation). An overview of the many approaches to postcode validation and the tradeoffs\n\n## Getting Started\n\n### Installation\n\n```bash\nnpm install postcode\n```\n\n### Validate\n\n```javascript\nimport { isValid } from \"postcode\";\n\nisValid(\"AA1 1AB\"); // =\u003e true\n```\n\n### Parse\n\nPass a string to `parse`. This will return a valid or invalid postcode instance which can be easily destructured.\n\n#### Valid Postcode\n\n`ValidPostcode` type definition\n\n```javascript\nimport { parse } from \"postcode\";\n\nconst {\n  postcode,    // =\u003e \"SW1A 2AA\"\n  outcode,     // =\u003e \"SW1A\"\n  incode,      // =\u003e \"2AA\"\n  area,        // =\u003e \"SW\"\n  district,    // =\u003e \"SW1\"\n  unit,        // =\u003e \"AA\"\n  sector,      // =\u003e \"SW1A 2\"\n  subDistrict, // =\u003e \"SW1A\"\n  valid,       // =\u003e true\n} = parse(\"Sw1A     2aa\");\n```\n\n#### Invalid Postcode\n\n`InvalidPostcode` type definition\n\n```javascript\nconst {\n  postcode,    // =\u003e null\n  outcode,     // =\u003e null\n  incode,      // =\u003e null\n  area,        // =\u003e null\n  district,    // =\u003e null\n  unit,        // =\u003e null\n  sector,      // =\u003e null\n  subDistrict, // =\u003e null\n  valid,       // =\u003e false\n} = parse(\"    Oh no, ):   \");\n```\n\n#### Type Guard\n\nThe TypeScript compiler can infer if you have a valid postcode type from `parse` by checking the `valid` attribute\n\n```javascript\nimport { parse } from \"postcode\";\n\nconst postcode = parse(\"SW1A 2AA\");\n\nif (postcode.valid) {\n  // `postcode` adheres to the `ValidPostcode` interface\n  processString(postcode.outcode.toLowerCase()); // TypeScript compiler knows `outcode` to be a string\n  processString(postcode.subDistrict.toLowerCase()); // And it will throw errors on common gotchas (e.g. subdistrict can be `null` on a valid postcode)\n} else {\n  // `postcode` adheres to the `InvalidPostcode` interface\n  processInvalidPostcode(postcode);\n}\n```\n\n#### Valid Postcode Object\n\n| Postcode | .outcode | .incode | .area | .district | .subDistrict | .sector | .unit |\n|----------|----------|---------|-------|-----------|--------------|---------|-------|\n| AA9A 9AA | AA9A     | 9AA     | AA    | AA9       | AA9A         | AA9A 9  | AA    |\n| A9A 9AA  | A9A      | 9AA     | A     | A9        | A9A          | A9A 9   | AA    |\n| A9 9AA   | A9       | 9AA     | A     | A9        | `null`       | A9 9    | AA    |\n| A99 9AA  | A99      | 9AA     | A     | A99       | `null`       | A99 9   | AA    |\n| AA9 9AA  | AA9      | 9AA     | AA    | AA9       | `null`       | AA9 9   | AA    |\n| AA99 9AA | AA99     | 9AA     | AA    | AA99      | `null`       | AA99 9  | AA    |\n\n### Exported Methods\n\nIf you're just after a single value, you can import a single method.\n\n#### Validation\n\n```javascript\nisValid(\"Sw1A 2aa\"); // =\u003e true\n```\n\n#### Formatting\n\n```javascript\nimport {\n  toNormalised,\n  toOutcode,\n  toIncode,\n  toArea,\n  toDistrict,\n  toSubDistrict,\n  toSector,\n  toUnit,\n} from \"postcode\";\n\ntoNormalised(\"Sw1A 2aa\");  // =\u003e \"SW1A 2AA\"\ntoOutcode(\"Sw1A 2aa\");     // =\u003e \"SW1A\"\ntoIncode(\"Sw1A 2aa\");      // =\u003e \"2AA\"\ntoArea(\"Sw1A 2aa\");        // =\u003e \"SW\"\ntoDistrict(\"Sw1A 2aa\");    // =\u003e \"SW1\"\ntoSubDistrict(\"Sw1A 2aa\"); // =\u003e \"SW1A\"\ntoSector(\"Sw1A 2aa\");      // =\u003e \"SW1A 2\"\ntoUnit(\"Sw1A 2aa\");        // =\u003e \"AA\"\n```\n\n#### Fix\n\n`fix` Attempts to correct and clean up a postcode without validating by replacing commonly misplaced characters (e.g. mixing up `0` and `\"O\"`, `1` and `\"I\"`). This method will also uppercase and fix spacing. The original input is returned if it cannot be reliably fixed.\n\n```javascript\nfix(\"SWIA 2AA\") =\u003e \"SW1A 2AA\" // Corrects I to 1\nfix(\"SW1A 21A\") =\u003e \"SW1A 2IA\" // Corrects 1 to I\nfix(\"SW1A OAA\") =\u003e \"SW1A 0AA\" // Corrects O to 0\nfix(\"SW1A 20A\") =\u003e \"SW1A 2OA\" // Corrects 0 to O\n\n// Other effects\nfix(\" SW1A  2AO\") =\u003e \"SW1A 2AO\" // Properly spaces\nfix(\"sw1a 2aa\") =\u003e \"SW1A 2AA\" // Uppercase\n```\n\nAims to be used in conjunction with parse to make postcode entry more forgiving:\n\n```javascript\nconst { inward } = parse(fix(\"SW1A 2A0\")); // inward = \"2AO\"\n```\n\nIf the input is not deemed fixable, the original string will be returned\n\n```javascript\nfix(\"12a\") =\u003e \"12a\"\n```\n\n#### Extract \u0026amp; Replace\n\n`match`. Retrieve valid postcodes in a body of text\n\n```javascript\nconst matches = match(\"The PM and her no.2 live at SW1A2aa and SW1A 2AB\"); // =\u003e [\"SW1A2aa\", \"SW1A 2AB\"]\n\n// Perform transformations like normalisation using `.map` and `toNormalised`\nmatches.map(toNormalised); // =\u003e [\"SW1A 2AA\", \"SW1A 2AB\"]\nmatches.map(toOutcode); // =\u003e [\"SW1A\", \"SW1A\"]\n\n// No matches yields empty array\nmatch(\"Some London outward codes are SW1A, NW1 and E1\"); // =\u003e []\n```\n\n`replace`. Replace postcodes in a body of text, returning the updated corpus and any matching postcodes\n\n```javascript\nconst { match, result } = replace(\"The PM and her no.2 live at SW1A2AA and SW1A 2AB\");\n// =\u003e match: [\"SW1A2AA\", \"SW1A 2AB\"]\n// =\u003e result: \"The PM and her no.2 live at  and \"\n\n// Add custom replacement\nreplace(\"The PM lives at SW1A 2AA\", \"Downing Street\");\n// =\u003e { match: [\"SW1A 2AA\"], result: \"The PM lives at Downing Street\" };\n\n// No match\nreplace(\"Some London outward codes are SW1A, NW1 and E1\");\n// =\u003e { match: [], result: \"Some London outward codes are SW1A, NW1 and E1\" }\n```\n\n## Version 5.0.0\n\n5.0.0 brings changes which allows for better treeshaking and interopability with ES Modules. It also deprecates legacy class based APIs in favour of single purpose methods.\n\n### Breaking Changes\n\n- `postcode` no longer exports a class. Legacy `new Postcode()` functionality has been removed. Methods attached to `Postcode` are all available as named exports.\n- `postcode` no longer uses default exports. All exports are named. E.g.\n\n```javascript\n// In \u003c= 4.0.0\nimport Postcode from \"postcode\";\nPostcode.parse(\"SW1A 2AA\");\n\n// In \u003e= 5.0.0\nimport { parse } from \"postcode\";\nparse(\"SW1A 2AA\");\n```\n\nIn many cases, migration can be achieved by changing `import Postcode from \"postcode\"` to `import * as Postcode from \"postcode\"`, however this gives up treeshaking advantages.\n\n### New Features\n\n- `postcode` now exports a ES Module build\n- Exports regular expressions\n- `match` accepts a string and returns all valid postcodes\n- `replace` accepts a string and replaces valid postcodes with an optional second argument. Default replacement text is empty string `\"\"`\n\n## Definitions\n\n[See the postcode format guide](https://ideal-postcodes.co.uk/guides/uk-postcode-format/) for a glossary of postcode component terms.\n\n## Notes\n\nPostcodes cannot be validated just with a regular expression (however complex). True postcode validation requires having a full list of postcodes to check against. Relying on a regex will produce false postives/negatives.\n\n[See the postcode validation guide](https://ideal-postcodes.co.uk/guides/postcode-validation) for an overview of the approaches and tradeoffs associated with postcode validation.\n\n## Testing\n\n```bash\nnpm test\n```\n\n## License\n\nMIT\n\nContains Ordnance Survey Data © Crown Copyright \u0026 Database Right\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fideal-postcodes%2Fpostcode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fideal-postcodes%2Fpostcode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fideal-postcodes%2Fpostcode/lists"}