{"id":15458115,"url":"https://github.com/dmotz/taxa","last_synced_at":"2025-05-07T23:41:44.204Z","repository":{"id":20494472,"uuid":"23772771","full_name":"dmotz/taxa","owner":"dmotz","description":"📐 A tiny language inside JavaScript to enforce type signatures.","archived":false,"fork":false,"pushed_at":"2015-08-09T04:56:00.000Z","size":200,"stargazers_count":8,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-14T00:50:12.152Z","etag":null,"topics":["coffeescript","javascript","types"],"latest_commit_sha":null,"homepage":"","language":"CoffeeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"react-boilerplate/react-boilerplate","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dmotz.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":"2014-09-07T22:31:52.000Z","updated_at":"2023-10-17T18:20:49.000Z","dependencies_parsed_at":"2022-07-07T14:31:55.601Z","dependency_job_id":null,"html_url":"https://github.com/dmotz/taxa","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/dmotz%2Ftaxa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmotz%2Ftaxa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmotz%2Ftaxa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmotz%2Ftaxa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dmotz","download_url":"https://codeload.github.com/dmotz/taxa/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231391234,"owners_count":18369723,"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":["coffeescript","javascript","types"],"created_at":"2024-10-01T22:59:09.063Z","updated_at":"2024-12-26T18:10:37.619Z","avatar_url":"https://github.com/dmotz.png","language":"CoffeeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Taxa\n### A tiny language inside JavaScript to enforce type signatures\n[Dan Motzenbecker](http://oxism.com), MIT License\n\n[@dcmotz](http://twitter.com/dcmotz)\n\n\n```javascript\n// denotes that add() accepts two numbers and returns a third:\nadd = t('n,n n', function(a, b) { return a + b });\nadd(3, 7);\n// =\u003e 10\nadd('3', '7');\n// =\u003e Taxa: Expected number as argument 0, given string (3) instead.\n```\n\n## Brief\n\nTaxa is a small metaprogramming experiment that introduces a minimal grammar for\ntype annotations to JavaScript (and by extension, CoffeeScript).\n\nUnlike other projects of this nature, Taxa is purely a runtime type checker\nrather than a static analyzer. When a Taxa-wrapped function receives or returns\narguments of the wrong type, an exception is thrown.\n\nFurther unlike other type declaration projects for JavaScript, Taxa's DSL lives\npurely within the syntax of the language. There is no intermediary layer and no\npreprocessing is required.\n\n\n## Grammar\n\nTaxa type signatures are intended to be quick to type and to occupy few additional\ncolumns in your code.\n\nFollowing this spirit of brevity, examples are also shown in CoffeeScript as it's\na natural fit to Taxa's style.\n\nIn the following, Taxa is aliased as `t` (though `$` or `taxa` feel natural as well):\n\n```coffeescript\nt = require 'taxa'\n# or in a browser without a module loader:\nt = window.taxa\n```\n\n```javascript\nvar t = require('taxa');\n// or in a browser without a module loader:\nvar t = window.taxa;\n```\n\nA type signature is composed of two halves: the argument types and the return\ntype, separated by a space.\n\n```coffeescript\npluralize = t 'String String', (word) -\u003e word + 's'\n```\n\n```javascript\nvar pluralize = t('String String', function(word) {\n  return word + 's';\n});\n```\n\nThe above signature indicates a function that expects a single string argument\nand is expected to return a string as a result. If any other types are passed to\nit, an informative error will be thrown:\n\n```coffeescript\npluralize 7\n# =\u003e Taxa: Expected string as argument 0, given number (7) instead.\n```\n\n```javascript\npluralize(7);\n// =\u003e Taxa: Expected string as argument 0, given number (7) instead.\n```\n\n\n### Shorthand\n\nTaxa provides a shorthand for built-in types, indicated by their first letter.\nThe following is equivalent to the previous example:\n\n```coffeescript\nexclaim = t 's s', (word) -\u003e word + '!'\n```\n\n```javascript\nvar exclaim = t('s s', function(word) {\n  return word + '!';\n});\n```\n\nCapital letter shorthand works as well:\n\n```coffeescript\nexclaim = t 'S S', (word) -\u003e word + '!'\n```\n\n```javascript\nvar exclaim = t('S S', function(word) {\n  return word + '!';\n});\n```\n\nThe shorthand mapping is natural, with the exception of `null`:\n\n- `0 =\u003e null`\n- `a =\u003e array`\n- `b =\u003e boolean`\n- `f =\u003e function`\n- `n =\u003e number`\n- `o =\u003e object`\n- `s =\u003e string`\n- `u =\u003e undefined`\n\nMultiple arguments are separated by commas:\n\n```coffeescript\nadd = t 'n,n n', (a, b) -\u003e a + b\n```\n\n```javascript\nvar add = t('n,n n', function(a, b) {\n  return a + b;\n});\n```\n\nThe above function is expected to take two numbers as arguments and return a third.\n\n\n### Ignores\n\nOccasionally you may want to ignore type checking on a particular argument.\nUse the `_` character to mark it as ignored in the signature. For example, you may\nhave a method that produces effects without returning a value:\n\n```coffeescript\nPopulation::setCount = t 'n _', (@count) -\u003e\n```\n\n```javascript\nPopulation.prototype.setCount = t('n _', function(count) {\n  this.count = count;\n});\n```\n\nOr a function that computes a result without input:\n```coffeescript\nt '_ n', -\u003e Math.PI / 2\n```\n\n```javascript\nt('_ n', function() {\n  return Math.PI / 2;\n});\n```\n\n### Optionals\n\nSimilarly you can specify arguments as optional and their type will only be\nchecked if a value is present:\n\n```coffeescript\nt 's,n? n', (string, radix = 10) -\u003e parseInt string, radix\n```\n\n```javascript\nt('s,n? n', function(string, radix) {\n  if (radix == null) {\n    radix = 10;\n  }\n  return parseInt(string, radix);\n});\n```\n\n### Ors\n\nFor polymorphic functions that accept different types of arguments, you can use\nthe `|` character to separate types.\n\n```coffeescript\ncombine = t 'n|s,n|s n|s', (a, b) -\u003e a + b\n```\n\n```javascript\nvar combine = t('n|s,n|s n|s', function(a, b) {\n  return a + b;\n});\n```\n\nFor each argument and return type in the above function, either a number or a\nstring is accepted.\n\n\n## Complex Types\n\nIf you'd like to enforce types that are more specific than primitives, objects,\nand arrays, you're free to do so:\n\n```coffeescript\nmakeDiv = t '_ HTMLDivElement', -\u003e document.createElement 'div'\n```\n\n```javascript\nvar makeDiv = t('_ HTMLDivElement', function() {\n  return document.createElement('div');\n});\n```\n***\n```coffeescript\nmakeBuffer = t 'n Buffer', (n) -\u003e new Buffer n\n```\n\n```javascript\nvar makeBuffer = t('n Buffer', function(n) {\n  return new Buffer(n);\n});\n```\n\nSince all non-primitive types are objects, specifying `o` in your signatures will\nof course match complex types as well. However, passing a plain object or an\nobject of another type to a function that expects a specific type (e.g. `WeakMap`)\n will correctly throw an error.\n\nKeep in mind that Taxa is strict with these signatures and will not walk up an\nobject's inheritance chain to match ancestral types.\n\n\n## Partial Application\nLike any other function, those annotated with Taxa carry a `bind` method, which\nworks as expected with the additional promise of modifying the output function's\nTaxa signature.\n\nFor example:\n\n```coffeescript\nadd  = t 'n,n n', (a, b) -\u003e a + b\nadd2 = add.bind @, 2\nadd2 3\n# =\u003e 5\n```\n\n```javascript\nvar add = t('n,n n', function(a, b) {\n  return a + b;\n});\nvar add2 = add.bind(this, 2);\nadd2(3);\n// =\u003e 5\n```\n\nUnder the covers, `add2`'s type signature was changed to `n n`.\n\n\n## Aliases\n\nYou can add your own custom shorthand aliases like this:\n\n```coffeescript\nt.addAlias 'i8', 'Int8Array'\n```\n\n```javascript\nt.addAlias('i8', 'Int8Array');\n```\n\nAnd remove them as well:\n\n```coffeescript\nt.removeAlias 'i8'\n```\n\n```javascript\nt.removeAlias('i8');\n```\n\n\n## Disabling\n\nYou can disable Taxa's type enforcement behavior globally by calling `t.disable()`\n(where `t` is whatever you've aliased Taxa as). This will cause calls to `t()` to\nperform a no-op wherein the original function is returned unmodified.\n\nThis is convenient for switching between environments without modifying code.\n\nIts counterpart is naturally `t.enable()`.\n\n\n## Further Examples\n\nTake a look at the test cases in `./test/main.coffee` for more examples of\nTaxa signatures.\n\n\n## Caveats\n\nWhen a function is modified by Taxa, its arity is not preserved as most JS\nenvironments don't allow modifying a function's length property. Workarounds to\nthis problem would involve using the `Function` constructor which would introduce\nits own problems. This only has implications if you're working with higher order\nfunctions that work by inspecting arity.\n\nIt should go without saying, but this library is experimental and has obvious\nperformance implications.\n\nTaxa is young and open to suggestions / contributors.\n\n\n## Name\nFrom the Ancient Greek τάξις (arrangement, order).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmotz%2Ftaxa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdmotz%2Ftaxa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmotz%2Ftaxa/lists"}