{"id":26358383,"url":"https://github.com/lazarljubenovic/type-guards","last_synced_at":"2025-03-16T14:27:48.000Z","repository":{"id":42206806,"uuid":"138850370","full_name":"lazarljubenovic/type-guards","owner":"lazarljubenovic","description":"Simple utility for runtime type checking which also assigns the correct type if used with TypeScript.","archived":false,"fork":false,"pushed_at":"2023-03-08T19:13:16.000Z","size":74,"stargazers_count":36,"open_issues_count":23,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-04T07:48:06.918Z","etag":null,"topics":["assert","assertion","guard","guards","types","typesafe","typescript"],"latest_commit_sha":null,"homepage":null,"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/lazarljubenovic.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-27T08:10:43.000Z","updated_at":"2023-12-07T17:45:28.000Z","dependencies_parsed_at":"2024-06-18T18:37:00.020Z","dependency_job_id":"1596f18e-ac39-4770-a062-fd26e3aec899","html_url":"https://github.com/lazarljubenovic/type-guards","commit_stats":{"total_commits":56,"total_committers":11,"mean_commits":5.090909090909091,"dds":0.6607142857142857,"last_synced_commit":"c699ee2f94ae5283591fe7a9895d0afcaa36ae14"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lazarljubenovic%2Ftype-guards","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lazarljubenovic%2Ftype-guards/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lazarljubenovic%2Ftype-guards/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lazarljubenovic%2Ftype-guards/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lazarljubenovic","download_url":"https://codeload.github.com/lazarljubenovic/type-guards/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243881179,"owners_count":20362913,"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":["assert","assertion","guard","guards","types","typesafe","typescript"],"created_at":"2025-03-16T14:27:47.441Z","updated_at":"2025-03-16T14:27:47.987Z","avatar_url":"https://github.com/lazarljubenovic.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `type-guards`\n\nThis module allows you to write run-time validation in a clear way in a strongly-typed manner.\nIn other words, it gives you a nice way to keep your code DRY by writing the validation function, and get the TypeScript types with it.\n\n## Installation\n\n```text\n$ yarn add type-guards\n```\n\n## Examples\n\n```ts\nimport * as tg from 'type-guards'\nconst isUser = tg.isOfShape({\n  name: tg.isString,\n  age: tg.isNumber,\n})\n\n// we purposely mark it as \"any\" to imitate API response or user's input\n// (anything generated at runtime which we cannot give a static type to)\nconst john: any = { name: 'John', age: 21 }\n\nif (isUser(john)) {\n  john.name // typesafe, this is a string\n  john.age // typesafe, this is a number\n  john.years // error\n}\n```\n\n## List of functions\n\n### `is`\n\nCreate a validator that asserts that the given argument is strictly equal (`===`) to something.\nNot very useful on its own.\n\n### `isOneOf`\n\nCreate a validator that asserts that at least one of the validators passed as arguments are passing.\n\n```ts\nconst isAbc = isOneOf(is('a'), is('b'), is('c'))\nisAbc('a') // =\u003e true\nisAbc('b') // =\u003e true\nisAbc('c') // =\u003e true\nisAbc('d') // =\u003e false\n```\n\n### `isEnum`\n\nCreate a validator that asserts that the given arguments is exactly one of the given arguments.\nFor example, the validator form the previous example can be written in a more simple way.\n\n```ts\nconst isAbc = isEnum('a', 'b', 'c')\n```\n\nIf all the arguments are of the same type, it will be inferred; so the above example will assert for string. If you have an enum, list all its values [somehow](https://github.com/Microsoft/TypeScript/issues/17198) in an array, and use the spread operator to pass the values in.\n\n```ts\nenum Gender { Male = 'm', Female = 'f' }\nconst GENDERS = [ Gender.Male, Gender.Female ]\nconst isGender = isEnum(...GENDERS) // a guard for type Gender\n```\n\n### `isNull`\n\nA validator that asserts that the given argument is `null`. Short for `is(null)`\n\n### `isUndefined`\n\nA validator that asserts that the given argument is `undefined`. Short for `is(undefined)`.\n\n### `isNullOrUndefined`, `isNullish`\n\nA validator that asserts that the given argument is `null` or `undefined` (like doing `arg == null`).\nShort for `isOneOf(is(null), is(undefined))`.\n\nAn alias with a shorten yet recognizable name is `isNullish`.\n\n### `isNotNull`, `isNotUndefined`, `isNotNullOrUndefined`, `isNotNullish`\n\nThe opposite of the previous three validators.\n\nA common use-case is filtering an array to get rid of nullish values:\n\n```ts\nconst array: Array\u003cnumber | null | undefined\u003e = [0, null, 1, undefined, 2]\nconst filtered = array.filter(tg.isNotNullish)\n// type of `filtered` is `Array\u003cnumber\u003e`\n```\n\n[Doesn't work perfectly](https://stackoverflow.com/questions/56949854/a-not-null-type-guard-resolves-to-never-in-the-else-branch) with the `else` branch, but this is a less common use-case. Either way, help is appreciated in the SO thread if you know more about this.\n\n### `isOfBasicType`\n\nCreate a validator that asserts that the given argument is of a certain type.\nThis is a wrapper around `typeof` checks and works with `string`, `number`, `boolean`, `symbol`, `function` and `object`.\n\n### `isString`, `isNumber`, `isBoolean`, `isSymbol`, `isObject`, `isFunction`.\n\nValidators that assert that the given argument is of the correct type.\nShort for `isOfBasicType('string')`, `isOfBasicType('number')`, etc.\n\nInstead of `isObject`, you probably need `isShapeOf` instead, which gives you more control over the type.\n\n### `isInstanceOf`\n\nCreate a validator that asserts that utilized the mechanism of `instanceof` keyword in JavaScript.\n\n### `isArrayOf`\n\nCreate a validator that asserts the given argument is an array,\nwhere each of its item is of a certain type.\nThe type of the items is passed as the argument of `isArrayOf`.\n\n```ts\nconst areNumbers = isArrayOf(isNumber)\nareNumbers([1, 2, 3]) // =\u003e true\nareNumbers(1) // =\u003e false\nareNumbers([1, 2, '3']) // =\u003e false\nareNumbers([1, 2, undefined]) // =\u003e false\n``` \n\nOf course, feel free to combine validators.\n\n```ts\nconst areKindaNumbers = isArrayOf(isOneOf(isNumber, isNullOrUndefined))\nareNumbers([1, 2, 3]) // =\u003e true\nareNumbers([1, 2, null, 4, undefined]) // =\u003e true\n```\n\n### `isOfShape`\n\nCreate a validator that asserts that the given argument is an object,\nwhere each of the values of its keys correspond to the given shape.\nThe shape is an object where the values are either new shapes or simple type checks.\n`isOfShape` allows objects that have extra keys.  See `isOfExactShape` to exclude\nobjects having extra keys not defined by the shape.\n\n```ts\nconst isUser = isOfShape({ name: isString, age: isNumber })\nisUser({name: 'John', age: 21}) // =\u003e true\nisUser({name: 'John', years: 21}) // =\u003e false\nisUser({name: 'John', age: 21, years: 21}) // =\u003e true\nisUser({name: 'John'}) // =\u003e false\n\nconst isCompany = isOfShape({\n  name: isString,\n  users: isArrayOf(isUser),\n})\nisCompany({name: 'Untitled', users: [{name: 'John', age: 21}]) // =\u003e true\n```\n\n### `isOfExactShape`\n\nThe same as `isOfShape`, except that it excludes objects that have extra keys\nnot defined by the shape.\n\n```ts\nconst isUser = isOfExactShape({ name: isString, age: isNumber })\nisUser({name: 'John', age: 21}) // =\u003e true\nisUser({name: 'John', years: 21}) // =\u003e false\nisUser({name: 'John', age: 21, years: 21}) // =\u003e false\nisUser({name: 'John'}) // =\u003e false\n```\n\n### `isTuple`\n\nCreate a validator that asserts that passed argument is a tuple of certain elements.\n\n```ts\nconst isNamePair = isTuple(isString, isString)\n\nisNamePair(['Walter', 'Jessie']) // =\u003e true\nisNamePair('Gustavo') // =\u003e false\nisNamePair(['Hector']) // =\u003e false\nisNamePair(['Walter', 'Jessie', 'Mike']) // =\u003e false\n```\n\n### `pick`\n\nCreate a validator which utilizes an already created validator and picks only a part of it.\n\n```ts\nconst fullUser = isOfShape({ name: isString, age: isNumber })\nconst partOfUser1 = pick(fullUser, 'name')\nconst partOfUser2 = isOfShape({ name: isString })\n// the two consts above produce the same validator\n```\n\n### `omit`\n\nCreate a validator which utilizes an already created validator and omits a part of it.\n\n```ts\nconst fullUser = isOfShape({ name: isString, age: isNumber })\nconst partOfUser1 = omit(fullUser, 'age')\nconst partOfUser2 = isOfShape({ name: isString })\n// the two consts above produce the same validator\n```\n\n### `partial`\n\nCreate a validator which utilizes an already created validator but allows `undefined` for every value.\n\n```ts\nconst fullUser = isOfShape({ name: isString, age: isNumber })\nconst partOfUser1 = partial(fullUser)\nconst partOfUser2 = isOfShape({ name: one(isUndefined, isString), age: isOneOf(isUndefined, isNumber) })\n// the two consts above produce the same validator\n```\n\nNote, however:\n\n```ts\nconst partOfUser = partial(fullUser)\npartOfUser({ name: 'John', age: 21 }) // =\u003e true\npartOfUser({ name: 'John' }) // =\u003e false (missing \"age\")\npartOfUser({ name: 'John', age: undefined }) =\u003e true \n```\n\nCurrently working on making the second one return `true` as well.\n\n## Using the type only\n\nIf you do not need to use the validator, but only want the type information, you can do that as well.\n\n```ts\ntype Number = FromGuard\u003ctypeof isNumber\u003e // : number\n\nconst isUser = isOfShape({ name: isString, age: isNumber })\ntype User = FromGuard\u003ctypeof isUser\u003e // : { name: string, age: number }\n```\n\nThis means that your codebase can have validators \"just in case\", but if you never use them, it will not increase your bundle size.\nYou could also set up your build pipeline in such way that the validators are run only in development mode.\n\n## Run-time assertion\n\nYou usually want to throw an exception at run-time in case the state of the application becomes unexpected.\nFor example, you might have `public foo?: string` in the class, but at some place you're certain that `foo` must be defined.\nInstead of doing `this.foo!`, which is just a build-time assertion, you might want to perform a run-time assertion such as the following.\n\n\n```typescript\nif (this.foo === undefined) {\n  throw new Error(`Unexpected value \"undefined\".`) \n}\n```\n\nTypeScript will properly assert here that `this.foo` is `Exclude\u003cstring | undefined, undefined\u003e` below the `if` block, which boils down to `string`.\n\nHowever, this becomes quite annoying to write all the time.\nHence, `throwIf` helper.\n\n```typescript\nconst foo = tg.throwIf(tg.isUndefined)(this.foo)\n```\n\nOr, create a reusable function.\nThis is the recommended way.\n\n```typescript\nconst throwIfUndefined = tg.throwIf(tg.isUndefined, `Unexpected \"undefined\" value.`)\nconst foo = throwIfUndefined(this.foo, `\"this.foo\" should've been defined here. Something's wrong.`)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flazarljubenovic%2Ftype-guards","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flazarljubenovic%2Ftype-guards","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flazarljubenovic%2Ftype-guards/lists"}