Composable type-safety checks.
Installation
Add this line to your application's Gemfile:
gem "fried-typings"And then execute:
$ bundle
Or install it yourself as:
$ gem install fried-typings
Usage
Let's say you have a class Hello which accepts a name as argument, and you
want to ensure it's a String:
require "fried/typings"
class Hello
include Fried::Typings
def call(name)
Is[String].(name)
"Hello, #{name}"
end
end
hello = Hello.new
hello.("Francesco") # => "Hello, Francesco"
hello.(123) # => raises TypeErrorYou can nest checks too:
one_of = OneOf[Numeric, IsStrictly[StandardError]]
one_of.(123) # => 123
one_of.(StandardError.new) # => #<StandardError: StandardError>
one_of.(ArgumentError.new) # => raises TypeErrorAnd if you don't want to raise error, just use #valid?
one_of = OneOf[Numeric, IsStrictly[StandardError]]
one_of.valid?(123) # => true
one_of.(ArgumentError.new) # => falseAvailable types
-
Is[type]checks that objectis_a?(type) -
IsStrictly[type]check thatobject.class == type -
OneOf[type1, type2, ...typeN]checks that object passIs[typeN]for any of the types -
StrictlyOneOf[type1, type2, ...typeN]checks that object passIsStrictly[typeN]for any of the types -
Anythingmatches any object -
Nothingnever matches an object -
Booleanchecks that object is eithertrueorfalse -
ArrayOf[type]checks that all element of the array passIs[type] -
HashOf[key_type, value_type]checks that all pairs of hash passIs[key_type]andIs[value_type] -
EnumeratorOf[type]checks that all element of the enumerator passIs[type] -
TupleOf[type1, type2, ...typeN]checks that each object of the array passesIs[typeN]the type at the same index in[]. If array size differ from the amount of specified types, it doesn't pass. E.g.:TupleOf[String, Numeric].valid?(["test", 123]) # => true. WhileTupleOf[String, Numeric].valid?([nil, 123]) # => false. Finally,TupleOf[String].valid?(["test", 123]) # => falsebecause array size don't match
Custom types
You can build easily your custom types:
class Is
include MetaType
include Type
def initialize(type)
@type = type
end
def valid?(obj)
# If it's one of the `Type` from Fried::Typings, check with those, to
# allow chaining/nesting
return type.valid?(obj) if @type < Type
# Otherwise perform the check how we would do
obj.is_a?(@type)
end
endThis will allow the following usage:
And yes this is exactly how Is is implemented. However, it deserves some
explaination.
Type does all the heavy lifting. You would need only that. MetaType adds
a class method [] that delegates directly to new.
You don't need MetaType, it's just there to improve syntax.
Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/Fire-Dragon-DoL/fried-typings.