{"id":27910637,"url":"https://github.com/janmalch/ts-code-contracts","last_synced_at":"2025-05-06T09:49:34.255Z","repository":{"id":42664535,"uuid":"302123888","full_name":"JanMalch/ts-code-contracts","owner":"JanMalch","description":"Design by contract with TypeScript.","archived":false,"fork":false,"pushed_at":"2024-01-20T10:15:49.000Z","size":433,"stargazers_count":34,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-22T10:46:23.616Z","etag":null,"topics":["hacktoberfest","library","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JanMalch.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-10-07T18:20:51.000Z","updated_at":"2025-02-19T21:05:17.000Z","dependencies_parsed_at":"2024-01-20T11:26:51.660Z","dependency_job_id":"0abba2e7-c523-4309-924f-743abe63a3af","html_url":"https://github.com/JanMalch/ts-code-contracts","commit_stats":{"total_commits":40,"total_committers":4,"mean_commits":10.0,"dds":0.375,"last_synced_commit":"7fcaf6199252265ac797b1e051b5ec79ee843ebe"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JanMalch%2Fts-code-contracts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JanMalch%2Fts-code-contracts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JanMalch%2Fts-code-contracts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JanMalch%2Fts-code-contracts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JanMalch","download_url":"https://codeload.github.com/JanMalch/ts-code-contracts/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252661597,"owners_count":21784651,"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":["hacktoberfest","library","typescript"],"created_at":"2025-05-06T09:49:29.434Z","updated_at":"2025-05-06T09:49:34.250Z","avatar_url":"https://github.com/JanMalch.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ts-code-contracts \u003ca href=\"https://www.github.com/JanMalch/ts-code-contracts\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/25508038/63974103-75242700-caac-11e9-8ca4-71cc5b905e90.png\" width=\"90\" height=\"90\" align=\"right\"\u003e\u003c/a\u003e\n\n[![npm](https://img.shields.io/npm/v/ts-code-contracts)](https://www.npmjs.com/package/ts-code-contracts)\n[![Build](https://github.com/JanMalch/ts-code-contracts/workflows/Build/badge.svg)](https://github.com/JanMalch/ts-code-contracts/workflows/Build)\n[![coverage](https://img.shields.io/badge/coverage-100%25-success)](https://github.com/JanMalch/ts-code-contracts/blob/master/jest.config.js#L14-L17)\n[![minified + gzip](https://badgen.net/bundlephobia/minzip/ts-code-contracts)](https://bundlephobia.com/result?p=ts-code-contracts)\n\n_Design by contract with TypeScript._\n\n## Installation \u0026 Usage\n\n```\nnpm i ts-code-contracts\n```\n\n\u003e Requires TypeScript^3.7\n\nYou can now import the following functions `from 'ts-code-contracts'`:\n\n- [`requires` for preconditions](#requires)\n  - [`requiresNonNullish` for null-checks as preconditions](#requiresnonnullish)\n- [`checks` for invariants](#checks)\n  - [`checksNonNullish` for null-checks as invariants](#checksnonnullish)\n- [`ensures` for postconditions](#ensures)\n  - [`ensuresNonNullish` for null-checks as postconditions](#ensuresnonnullish)\n- [`asserts` for impossible events](#asserts)\n- [`unreachable` for unreachable code branches](#unreachable)\n- [`error` to make code more concise](#error)\n- [`isDefined` type guard](#isdefined)\n\nMake sure to checkout the examples in the documentation below\nor refer to the [test cases](https://github.com/JanMalch/ts-code-contracts/blob/master/index.test.ts#L133-L163)\nand [typing assistance](https://github.com/JanMalch/ts-code-contracts/blob/master/index.test-d.ts#L41-L52)!\n\nContracts are really just handy shorthands to throw an error, if the given condition is not met.\nAnd yet they greatly help the compiler and the readability of your code.\n\n## `requires`\n\nUse it to validate preconditions, like validating arguments.\nThrows a `PreconditionError` if the `condition` is `false`.\n\n```ts\nfunction requires(\n  condition: boolean,\n  message: string = 'Unmet precondition'\n): asserts condition;\n```\n\n- `condition` - the condition that should be `true`\n- `message` - an optional message for the error\n\n**Example:**\n\n```ts\nfunction myFun(name: string) {\n  requires(name.length \u003e 10, 'Name must be longer than 10 chars');\n}\n```\n\n## `requiresNonNullish`\n\nA variation of `requires` that returns the given value unchanged if it is not `null` or `undefined`.\nThrows a `PreconditionError` otherwise.\n\n```ts\nfunction requiresNonNullish\u003cT\u003e(\n  value: T,\n  message = 'Value must not be null or undefined'\n): NonNullable\u003cT\u003e;\n```\n\n- `value` - the value that should not be `null` or `undefined`\n- `message` - an optional message for the error\n\n**Example:**\n\n```ts\nfunction myFun(name: string | null) {\n  const nameNonNull = requiresNonNullish(name, 'Name must be defined');\n  nameNonNull.toUpperCase(); // no compiler error!\n}\n```\n\n## `checks`\n\nUse it to check for an illegal state.\nThrows a `IllegalStateError` if the `condition` is `false`.\n\n```ts\nfunction checks(\n  condition: boolean,\n  message = 'Callee invariant violation'\n): asserts condition;\n```\n\n- `condition` - the condition that should be `true`\n- `message` - an optional message for the error\n\n**Example:**\n\n```ts\nclass Socket {\n  private isOpen = false;\n  send(data: Data) {\n    check(this.isOpen, 'Socket must be open');\n  }\n  open() {\n    this.isOpen = true;\n  }\n}\n```\n\n## `checksNonNullish`\n\nA variation of `checks` that returns the given value unchanged if it is not `null` or `undefined`.\nThrows a `IllegalStateError` otherwise.\n\n```ts\nfunction checksNonNullish\u003cT\u003e(\n  value: T,\n  message = 'Value must not be null or undefined'\n): NonNullable\u003cT\u003e;\n```\n\n- `value` - the value that should not be `null` or `undefined`\n- `message` - an optional message for the error\n\n**Example:**\n\n```ts\nclass Socket {\n  data: Data | null = null;\n  send() {\n    const validData = checksNonNullish(this.data, 'Data must be available');\n    validData.send(); // no compiler error!\n  }\n}\n```\n\n## `ensures`\n\nUse it to verify that your code behaved correctly.\nThrows a `PostconditionError` if the `condition` is `false`.\n\n```ts\nfunction ensures(\n  condition: boolean,\n  message = 'Unmet postcondition'\n): asserts condition;\n```\n\n- `condition` - the condition that should be `true`\n- `message` - an optional message for the error\n\n**Example:**\n\n```ts\nfunction myFun() {\n  createPerson({ id: 0, name: 'John' });\n  const entity = findById(0); // returns null if not present\n  return ensures(isDefined(entity), 'Failed to persist entity');\n}\n```\n\n## `ensuresNonNullish`\n\nA variation of `ensures` that returns the given value unchanged if it is not `null` or `undefined`.\nThrows a `PostconditionError` otherwise.\n\n```ts\nfunction ensuresNonNullish\u003cT\u003e(\n  value: T,\n  message = 'Value must not be null or undefined'\n): NonNullable\u003cT\u003e;\n```\n\n- `value` - the value that should not be `null` or `undefined`\n- `message` - an optional message for the error\n\n**Example:**\n\n```ts\nfunction myFun(): Person {\n  createPerson({ id: 0, name: 'John' });\n  const entity = findById(0); // returns null if not present\n  return ensuresNonNullish(entity, 'Failed to persist entity');\n}\n```\n\n## `asserts`\n\nClarify that you think that the given condition is impossible to happen.\nThrows a `AssertionError` if the `condition` is `false`.\n\n```ts\nasserts(\n  condition: boolean,\n  message?: string\n): asserts condition;\n```\n\n- `condition` - the condition that should be `true`\n- `message` - an optional message for the error\n\n## `unreachable`\n\nAsserts that a code branch is unreachable. If it is, the compiler will throw a type error.\nIf this function is reached at runtime, an error will be thrown.\n\n```ts\nfunction unreachable(\n  value: never,\n  message = 'Reached an unreachable case'\n): never;\n```\n\n- `value` - a value\n- `message` - an optional message for the error\n\n**Example:**\n\n```ts\nfunction myFun(foo: MyEnum): string {\n  switch (foo) {\n    case MyEnum.A:\n      return 'a';\n    case MyEnum.B:\n      return 'b';\n    // no compiler error if MyEnum only has A and B\n    default:\n      unreachable(foo);\n  }\n}\n```\n\n## `error`\n\nThis function will always throw an error.\nIt helps keeping code easy to read and come in handy when assigning values with a ternary operator or the null-safe operators.\n\n```ts\nfunction error(message?: string): never;\nfunction error(\n  errorType: new (...args: any[]) =\u003e Error,\n  message?: string\n): never;\n```\n\n- `errorType` - an error class, defaults to `IllegalStateError`\n- `message` - an optional message for the error\n\n**Example:**\n\n```ts\nfunction myFun(foo: string | null) {\n  const bar = foo ?? error(PreconditionError, 'Argument may not be null');\n  const result = bar.length \u003e 0 ? 'OK' : error('Something went wrong!');\n}\n```\n\n## `isDefined`\n\nA type guard, to check that a value is not `null` or `undefined`.\nMake sure to use [`strictNullChecks`](https://basarat.gitbook.io/typescript/intro/strictnullchecks).\n\n```ts\nfunction isDefined\u003cT\u003e(value: T): value is NonNullable\u003cT\u003e;\n```\n\n- `value` - the value to test\n\n**Example:**\n\n```ts\nconst x: string | null = 'Hello';\nif (isDefined(x)) {\n  x.toLowerCase(); // no compiler error!\n}\n```\n\n## Errors\n\nThe following error classes are included:\n\n- `PreconditionError` \u0026rarr; An error thrown, if a precondition for a function or method is not met.\n- `IllegalStateError` \u0026rarr; An error thrown, if an object is an illegal state.\n- `PostconditionError` \u0026rarr; An error thrown, if a function or method could not fulfil a postcondition.\n- `AssertionError` \u0026rarr; An error thrown, if an assertion has failed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanmalch%2Fts-code-contracts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjanmalch%2Fts-code-contracts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanmalch%2Fts-code-contracts/lists"}