{"id":18017834,"url":"https://github.com/zac-garby/argtyper","last_synced_at":"2025-03-26T19:34:00.540Z","repository":{"id":57183618,"uuid":"84718621","full_name":"zac-garby/argtyper","owner":"zac-garby","description":"A JavaScript argument-type-checker, without the need for preprocessing or compiling.","archived":false,"fork":false,"pushed_at":"2017-10-14T20:41:19.000Z","size":74,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-22T08:02:33.062Z","etag":null,"topics":["checker","functions","javascript","javascript-library","library","npm-package","package","types"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/argtyper","language":"JavaScript","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/zac-garby.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-12T10:54:43.000Z","updated_at":"2018-11-29T19:20:17.000Z","dependencies_parsed_at":"2022-08-23T01:20:42.603Z","dependency_job_id":null,"html_url":"https://github.com/zac-garby/argtyper","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zac-garby%2Fargtyper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zac-garby%2Fargtyper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zac-garby%2Fargtyper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zac-garby%2Fargtyper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zac-garby","download_url":"https://codeload.github.com/zac-garby/argtyper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245722813,"owners_count":20661830,"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":["checker","functions","javascript","javascript-library","library","npm-package","package","types"],"created_at":"2024-10-30T04:25:52.505Z","updated_at":"2025-03-26T19:34:00.026Z","avatar_url":"https://github.com/zac-garby.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# argtyper\n\n### JS Type-Constraints without compilation.\n\nType checking is very useful in JavaScript - it helps catch a number of different bugs.\nHowever, to actually use type checking normally, you'd install a library such as Flow,\nwhich is great, but you have to compile your program. This not only takes time, but is\nannoying to set up.\n\n_argtyper_ is a better way to implement type checking for function arguments and\nreturn types.\n\n### Features\n\n - **Argument types**\n - **Function return types**\n - **Type aliases** -- e.g. `Vector` \u0026rarr; `{ x: Number, y: Number }`\n - **Deep array and object typing** -- e.g. `[Number, [Number, [String, Number]]]`\n - **Polymorphic types** -- e.g. `Number | String` \u0026rarr; Either a number or a string\n - **Repeated types** -- e.g. `[Number * 5]` \u0026rarr; An array of five numbers\n - **Arrays of any length** -- e.g. `[...Number]` \u0026rarr; An array of any amount of numbers\n\n## Installation\n\nIf you're using npm, you can just run this command to install\n[_argtyper_](https://www.npmjs.com/package/argtyper):\n\n```\n$ npm install --save argtyper\n```\n\nAnd to import the _type_ function into a file, use the following:\n\n```javascript\nvar type = require('argtyper').type\n```\n\nYou can then just call _type_ on functions, as documented in the example below.\n\n## Example\n\nHere is a basic program using _argtyper_. In it, a simple function, called `add`,\nis defined, with two arguments, called _a_ and _b_. Both of them are _Number_'s\n: the allowed type is written following an equals, after the\nname of the argument.\n\n```javascript\nfunction add(a=Number, b=Number) {\n  return a + b\n}\n\nadd = type(add)\n```\n\nThe last line is very important. The _type_ function wraps a given function in some type\nchecking code and returns the new one.\n\nBelow are some test cases, showing what happens when `add` is executed with different\narguments.\n\n```javascript\n// Test cases\n\nadd(5, 3)                //=\u003e 8\nadd(5, true)             //=\u003e Error\nadd(6, 1, 8)             //=\u003e Error\nadd(7)                   //=\u003e Error\n```\n\nIt also works with arrow functions, which can be useful to make typed functions\na little faster to write. The function above can be rewritten as the following:\n\n```javascript\nvar add = type((a=Number, b=Number) =\u003e {\n  return a + b;\n});\n```\n\n### Typing objects\n\n_argtyper_ also has a function to type all functions in an object, called\n`typeAll()`. It takes one argument: _object_, which is the object to type.\n\nTo import it, use the following:\n\n```javascript\nvar typeAll = require('argtyper').typeAll\n```\n\nAnd here's how to use it:\n\n```javascript\nconst maths = {\n  add = function (a=Number, b=Number) {\n    return a + b;\n  },\n  mul = function (a=Number, b=Number) {\n    return a * b\n  }\n};\n\ntypeAll(maths) // Note you don't have to assign it back to the object\n\nmaths.add(5, 5)    //=\u003e 10\nmaths.mul(5, 5)    //=\u003e 25\nmaths.add('2', 10) //=\u003e Error\n```\n\nAs kind of demonstrated in that example, the `typeAll` function can be very\nuseful if you want to type a _module_, if that module is defined as properties\nof an object.\n\n## Documentation\n\n### Syntax overview\n\n#### Function syntax\n\nThe simplest sort of typing _argtyper_ supports is typing the arguments of a\nfunction, as demonstrated above:\n\n```javascript\nfunction fn (a=Number, b=String) {\n  ...\n}\n\nfn = type(fn) // Remember to call 'type'!\n```\n\nThis function would only accept two arguments. The first would would have to\nbe a number, and the second would have to be a string. If any of these requirements\nwere not met, an error would be thrown.\n\n---\n\nYou can also give a function a return type. This is only possible with arrow\nfunctions, due to the syntax of them:\n\n```javascript\nlet add = (a=Number | String, b=Number | String) =\u003e String =\u003e {\n  return a + b\n}\n\nadd = type(add)\n```\n\nDon't worry about the `Number | String` notation, it will be explained in the\nnext section.\n\nThis function takes two arguments, _a_ and _b_, both of them being either\na number or a string. The function can, however, _only_ return a string -\notherwise it will return an error\n\n---\n\nIf you want to use a more complex constraint as the return type, there are two\nways of doing so.\n\nFirstly, you could use `(_=Constraint)` notation:\n```javascript\nlet fn = (...) =\u003e (_=Number | String) =\u003e {\n  ...\n}\n```\n\nThis means you can use any of the constraints defined below, because without\nusing this syntax, javascript's grammar won't allow your function.\n\nThe second way is to define an alias for your complex type, turning it into a\nsimple identifier:\n\n```javascript\ntypedef(Vector =\u003e { x: Number, y: Number })\n```\n\nThen, you can just define your function like:\n\n```javascript\nlet fn = (...) =\u003e Vector =\u003e {\n  ...\n}\n```\n\n#### Constraints\n\nThere are many different types of constraints in _argtyper_. Here's a list!\n\n - `ClassName` - The simplest constraint, which you've already seen in the earlier\n   examples, is just a single class name, such as _Number_ or _String_.\n    - Don't use _Array_ or _Object_ as a class name, as they are to be written\n      using their own syntax (described below.)\n    - Also don't use _Any_, because it's it's own separate thing.\n    - Example: `Number` allows a number\n\n - `[Constraint, Constraint ...]` - When having an array as an argument to a\n   function, you specify the types for each element of that array. The syntax is\n   very similar to defining a normal array, except each element of the\n   constraining array should be another constraint (i.e. a class name,\n   another array, etc...)\n    - Example: `[Number, String, [Number, Number, Number]]` allows an array\n      where the first element is a number, the second a string, and the third\n      another array containing three numbers.\n\n - `{x: Constraint, y: Constraint ...}` - You can add an object constraint in a\n   similar fashion to an array. Again, you use the exact same syntax as writing\n   an object, just each property's value should be another constraint.\n    - Example: `{x: Number, y: Number}` allows a two-dimensional vector in the\n      form of an object with an x and y field, both numbers.\n\n - `Constraint | Constraint[ | Constraint ...]` - It's also possible for an argument to\n   accept multiple types, using the `|` operator. It's fairly simple - here's\n   an example:\n    - Example: `Number | String | Boolean` allows a number, string, or boolean\n\n - `Any` - The word _Any_ on its own just allows anything through. It's how\n   you can make an untyped argument in _argtyper_.\n\n - `[Constraint * amount]` - Is the same as writing\n   `[Constraint, Constraint ... (amount times)]`.\n    - Example: `[Number * 10]` allows an array of 10 numbers\n\n - `[...Constraint]` - A list of any size (except from 0) containing only\n   `Constraint`s.\n    - Example: `[...String]` allows an array of any size \u003e 0 of strings\n\n### Aliases - `typedef(Name =\u003e Constraint)`\n\nSay you're writing a game. You'd probably use a lot of Vectors for velocity,\nposition etc... In _argtyper_, you might represent a vector similar to the\nfollowing:\n\n```javascript\nfunction addThreeVectors (\n  a={x: Number, y: Number},\n  b={x: Number, y: Number},\n  c={x: Number, y: Number}\n) {\n  ...\n}\n```\n\nBut as you can see, it just takes too long to write. And imagine if you repeatedly\nused an object which has, say, 10 properties. It'd just take too long. There must\nbe a better way, right? Well, there is. You can use the `typedef` function,\nexported from _argtyper_:\n\n```javascript\nvar typedef = require('argtyper').typedef\n```\n\nThis is a very useful little function. Here's an example of its use:\n\n```javascript\ntypedef(Vector =\u003e ({x: Number, y: Number}))\n\nfunction addThreeVectors (a=Vector, b=Vector, c=Vector) {\n  ...\n}\n```\n\nMuch nicer! And also exactly 100% identical to the previous function, as the\naliases are automatically expanded upon parsing.\n\nNow, not only can you make an alias for an object (like the example above) but\nyou can actually make an alias for any of the following types:\n\n - Objects\n - Arrays\n - Actually, anything you can write as a constraint normally\n - Even other aliases\n\nHere are some (completely trivial) examples using a some alias types mentioned\nabove:\n\n```javascript\ntypedef(ThreeNumbers =\u003e [Number, Number, Number])\ntypedef(AddOperand =\u003e Number | String)\ntypedef(ThreeAddOperands =\u003e [AddOperand, AddOperand, AddOperand])\n\nfunction sumThree (a=ThreeNumbers) {\n  return a[0] + a[1] + a[2]\n}\n\nfunction add (a=AddOperand, b=AddOperand) {\n  return a + b\n}\n\nfunction addThree (ops=ThreeAddOperands) {\n  return ops[0] + ops[1] + ops[2]\n}\n```\n\n(I didn't call type on the functions defined. In real life, you'd need to, but\nto make it more readable I didn't in this example. I also probably won't in\nother examples)\n\n#### Aliases to shorten type names\n\nHere's another really useful use of aliases:\n\n```javascript\ntypedef(N =\u003e Number)\n```\n\nAs I mentioned earlier, aliases can be defined as _any_ valid constraint.\nTherefore, you can also use them to just shorten class names:\n\n```javascript\nfunction add (a=N, b=N) {\n  return a + b\n}\n```\n\n### Repetition - `[Constraint * n]`\n\nSometimes, you want an array with lots of elements in it. Here's an example:\n\n```javascript\nfunction sumOneHundred (a=[Number, Number, Number ... Number]) {\n  return a.reduce((a, b) =\u003e a + b, 0)\n}\n```\n\n(I omitted 96 `Number`s, but you can imagine how long it'd be if I wrote them all out)\n\nThere's a better way to do this, of course. You can use the `*` operator:\n\n```javascript\nfunction sumOneHundred (a=[Number * 100]) {\n  return a.reduce((a, b) =\u003e a + b, 0)\n}\n```\n\nAs you can see, this looks a lot better.\n\nTo pass the one hundred arguments to this function, you'd do the following:\n\n```javascript\nsumOneHundred([7, 2, 3, 10, 4, ...])\n```\n\nBut obviously just a whole lot more elements in the array.\n\n#### Infinite repetition\n\nYou can also define a constraint which matches a list of any size greater than 0\nusing the spread (`...`) operator:\n\n```javascript\nfunction sumN (xs=[...Number]) {\n  return xs.reduce((a, b) =\u003e a + b, 0)\n}\n\nsumN([1, 2, 3]) //=\u003e 6\nsumN([1])       //=\u003e 1\nsumN([])        //=\u003e Error\n```\n\nIf you also want to allow an array of length 0, you can use the following hack,\nuntil I add a special syntax for it:\n\n```javascript\nfunction sumN (xs=[] | [...Number]) {\n  return xs.reduce((a, b) =\u003e a + b, 0)\n}\n```\n\nWhich works because it can either match an empty array or an array with some\nnumbers in it.\n\n## Problems\n\nWell, \"Problem\". Basically, argtyper can be quite slow, so it's probably best not\nto use it for applications which need to be very performant.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzac-garby%2Fargtyper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzac-garby%2Fargtyper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzac-garby%2Fargtyper/lists"}