{"id":31764127,"url":"https://github.com/janlelis/sig","last_synced_at":"2025-10-09T23:45:18.355Z","repository":{"id":30377775,"uuid":"33930398","full_name":"janlelis/sig","owner":"janlelis","description":"Validate Method Arguments \u0026 Results in Ruby","archived":false,"fork":false,"pushed_at":"2021-12-29T20:57:50.000Z","size":22,"stargazers_count":57,"open_issues_count":0,"forks_count":2,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-09-15T03:37:56.688Z","etag":null,"topics":["contracts","ruby","ruby-methods","ruby-types","signatures","typechecker","types"],"latest_commit_sha":null,"homepage":"","language":"Ruby","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/janlelis.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-04-14T12:30:53.000Z","updated_at":"2025-04-08T17:14:38.000Z","dependencies_parsed_at":"2022-09-08T11:51:50.364Z","dependency_job_id":null,"html_url":"https://github.com/janlelis/sig","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/janlelis/sig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janlelis%2Fsig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janlelis%2Fsig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janlelis%2Fsig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janlelis%2Fsig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/janlelis","download_url":"https://codeload.github.com/janlelis/sig/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janlelis%2Fsig/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279002126,"owners_count":26083307,"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","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["contracts","ruby","ruby-methods","ruby-types","signatures","typechecker","types"],"created_at":"2025-10-09T23:45:16.685Z","updated_at":"2025-10-09T23:45:18.348Z","avatar_url":"https://github.com/janlelis.png","language":"Ruby","readme":"# `sig`: Optional Type Assertions for Ruby methods. [![[version]](https://badge.fury.io/rb/sig.svg)](https://badge.fury.io/rb/sig)  [![[ci]](https://github.com/janlelis/sig/workflows/Test/badge.svg)](https://github.com/janlelis/sig/actions?query=workflow%3ATest)\n\nThis gem adds the `sig` method that allows you to add signatures to Ruby methods. When you call the method, it will verify that the method's arguments/result fit to the previously defined behavior:\n\n```ruby\n# On main object\nsig [:to_i, :to_i], Integer,\ndef sum(a, b)\n  a.to_i + b.to_i\nend\n\nsum(42, false)\n# Sig::ArgumentTypeError:\n# - Expected false to respond to :to_i\n\n# In modules\nclass A\n  sig [Numeric, Numeric], Numeric,\n  def mul(a, b)\n    a * b\n  end\nend\n\nA.new.mul(4,\"3\")\n# Sig::ArgumentTypeError:\n# - Expected \"3\" to be a Numeric, but is a String\n\n\n# Explicitely define signature for singleton_class\nclass B\n  sig_self [:reverse],\n  def self.rev(object)\n    object.reverse\n  end\nend\n\nB.rev 42\n# Sig::ArgumentTypeError:\n# - Expected 42 to respond to :reverse\n```\n\nThe first argument is an array that defines the behavior of the method arguments, and the second one the behavior of the method result. Don't forget the trailing comma, because the method definition needs to be the last argument to the `sig` method.\n\n## Features \u0026 Design Goals\n* Provide an intuitive way to define signatures\n* Only do argument/result type checks, nothing else\n* Use Ruby's inheritance chain, don't redefine methods\n* Encourage duck typing\n* Should work with keyword arguments\n* Only target Ruby 2.1+\n\n### This is not static typing. Ruby is a dynamic language:\n\nNevertheless, nothing is wrong with ensuring specific behaviour of method arguments when you need it.\n\n### Is this better than rubype?\n\nThe rubype gem achieves similar things like sig (and inspired the creation of sig). It offers a different syntax and differs in feature \u0026 implementation details, so in the end, it is a matter of taste, which gem you prefer.\n\n## Setup\n\nAdd to your `Gemfile`:\n\n```ruby\ngem 'sig'\n```\n\n## Usage\n\nSee example at top for basic usage.\n\n### Supported Behavior Types\n\nYou can use the following behavior types in the signature definition:\n\nType    | Meaning\n------- | -------\nSymbol  | Argument must respond to a method with this name\nModule  | Argument must be of this module\nArray   | Argument can be of any type found in the array\ntrue    | Argument must be truthy\nfalse   | Argument must be falsy\nnil     | Wildcard for any argument\n\n### Example Signatures\n\n```ruby\nsig [:to_i], Numeric,              # takes any object that responds to :to_i as argument, numeric result\nsig [Numeric], String,             # one numeric argument, string result\nsig [Numeric, Numeric], String,    # two numeric arguments, string result\nsig [:to_s, :to_s],                # two arguments that support :to_s, don't care about result\nsig nil, String,                   # don't care about arguments, as long result is string\nsig {keyword: Integer}             # keyword argument must be an intieger\nsig [:to_f, {keyword: String}],    # mixing positional and keyword arguments is possible\nsig [[Numeric, NilClass]], Float   # one argument that must nil or numeric, result must be float\nsig [Numeric, nil,  Numeric],      # first and third argument must be numeric, don't care about type of second\n```\n\nSee source(https://github.com/janlelis/sig/blob/master/lib/sig.rb) or specs(https://github.com/janlelis/sig/blob/master/spec/sig_spec.rb) for more features.\n\n## Benchmark (Take with a Grain of Salt)\n\nYou can run `rake  benchmark` to run [it](https://github.com/janlelis/sig/blob/v1.0.1/Rakefile#L33-L148) on your machine.\n\nThere is still a lot room for performance improvements. Feel free to suggest some faster implementation to do the type checks (even if it is crazy and not clean, as long it does not add too much \"magic\", a.k.a does not make debugging harder).\n\nNote: Starting with 0.3.0, rubype uses a C extension, which makes it much faster. The benchmark is still run with rubype 0.2.5, because 0.3.x currently does not work on jruby \u0026 rbx.\n\n### MRI\n\n```\nruby version: 2.2.2\nruby engine: ruby\nruby description: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]\nsig version: 1.0.1\nrubype version: 0.2.5\ncontracts version: 0.9\nCalculating -------------------------------------\n                pure   107.628k i/100ms\n                 sig    14.425k i/100ms\n              rubype    12.715k i/100ms\n           contracts     7.688k i/100ms\n-------------------------------------------------\n                pure      6.856M (± 0.9%) i/s -     34.333M\n                 sig    192.440k (± 1.5%) i/s -    966.475k\n              rubype    164.811k (± 0.8%) i/s -    826.475k\n           contracts     90.089k (± 0.7%) i/s -    453.592k\n\nComparison:\n                pure:  6855615.3 i/s\n                 sig:   192439.7 i/s - 35.62x slower\n              rubype:   164810.5 i/s - 41.60x slower\n           contracts:    90088.6 i/s - 76.10x slower\n```\n\n### JRuby 9000\n\n```\nruby version: 2.2.2\nruby engine: jruby\nruby description: jruby 9.0.0.0-SNAPSHOT (2.2.2) 2015-05-04 6055b79 Java HotSpot(TM) 64-Bit Server VM 24.80-b11 on 1.7.0_80-b15 +indy +jit [linux-amd64]\nsig version: 1.0.1\nrubype version: 0.2.5\ncontracts version: 0.9\nCalculating -------------------------------------\n                pure    70.898k i/100ms\n                 sig     5.308k i/100ms\n              rubype     3.152k i/100ms\n           contracts   279.000  i/100ms\n-------------------------------------------------\n                pure      8.848M (±13.7%) i/s -     42.539M\n                 sig    178.169k (±10.3%) i/s -    881.128k\n              rubype    119.689k (±26.5%) i/s -    444.432k\n           contracts     56.780k (±16.8%) i/s -    265.887k\n\nComparison:\n                pure:  8848039.4 i/s\n                 sig:   178168.8 i/s - 49.66x slower\n              rubype:   119689.0 i/s - 73.93x slower\n           contracts:    56780.4 i/s - 155.83x slower\n```\n\n### RBX 2.5.3\n\n```\nruby version: 2.1.0\nruby engine: rbx\nruby description: rubinius 2.5.3.c25 (2.1.0 fbb3f1e4 2015-05-02 3.4 JI) [x86_64-linux-gnu]\nsig version: 1.0.1\nrubype version: 0.2.5\ncontracts version: 0.9\nCalculating -------------------------------------\n                pure   114.964k i/100ms\n                 sig     9.654k i/100ms\n              rubype     3.775k i/100ms\n           contracts     3.964k i/100ms\n-------------------------------------------------\n                pure     23.585M (± 3.3%) i/s -    117.263M\n                 sig    134.304k (± 3.1%) i/s -    675.780k\n              rubype     56.042k (± 1.7%) i/s -    283.125k\n           contracts     69.820k (± 1.8%) i/s -    348.832k\n\nComparison:\n                pure: 23585373.7 i/s\n                 sig:   134303.7 i/s - 175.61x slower\n           contracts:    69819.9 i/s - 337.80x slower\n              rubype:    56042.1 i/s - 420.85x slower\n```\n\n## Deactivate All Signature Checking\n\n```ruby\nrequire 'sig/none' # instead of require 'sig'\n```\n\n## Alternatives for Type Checking and More\n\n- https://github.com/gogotanaka/Rubype\n- https://github.com/egonSchiele/contracts.ruby\n- https://github.com/plum-umd/rtc\n\n## MIT License\n\nCopyright (C) 2015 Jan Lelis \u003chttps://janlelis.com\u003e. Released under the MIT license.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanlelis%2Fsig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjanlelis%2Fsig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanlelis%2Fsig/lists"}