Skip to content

Repository files navigation

Thy Build Status

Thy is a minimal, strict runtime type system for Ruby.

Motivation

There are many existing runtime type systems for Ruby, most notably, dry-types. Here's why you might prefer Thy:

  • Thy encourages strictness. Avoiding type coercion as much as possible is an excellent way to keep your code predictable and straightforward.
  • Minimalism. Thy's API only has what's needed, nothing more.
  • No Any type. Don't worry, if you have to, you can get it!

Installation

Add this line to your application's Gemfile:

gem'thy'

And then execute:

$ bundle

Or install it yourself as:

$ gem install thy

Usage

It's recommended not to use Thy directly (although you can), but to create a module for working with types, and to include Thy::Types into it.

moduleTypesincludeThy::Typesend

To run a type check, call check on a type you need. For example:

moduleTypesincludeThy::TypesendTypes::String.check('a string').success?# => trueTypes::Integer.check(3.14).success?# => false

If a check fails, a message describing the failure is provided:

Types::String.check(3).failure?# => trueTypes::String.check(3).message# => "Expected a String, but got: 3"

Custom types

Thy allows you to define custom types via Thy::Type's constructor:

moduleTypesincludeThy::TypesNonZeroValue=Thy::Type.new{ |value| value != 0}end

Providing meaningful error messages

moduleTypesincludeThy::TypesNonZeroValue=Thy::Type.newdo |value|
value != 0 || Thy::Result::Failure.new("Expected #{value.inspect} to be nonzero")endend

Building on top of existing types

Extending existing types is simple, too:

moduleTypesincludeThy::TypesNonZeroInteger=Thy.refine_type(Integer,Thy::Type.new{ |v| v != 0})end

Direct usage

You can use Thy types directly, for example, if you'd like to play around in the console:

Thy::String.check('Bob').success?# => truePositiveInteger=Thy.refine_type(Integer,Thy::Type.new{ |v| v > 0})

Built-in type reference

Primitive types

# StringThy::String.check('Bob').success?# => true# SymbolThy::Symbol.check(:bob).success?# => true# NumericThy::Numeric.check(3.14).success?# => trueThy::Numeric.check(0).success?# => true# FloatThy::Float.check(3.14).success?# => true# IntegerThy::Integer.check(3).success?# => true# BooleanThy::Boolean.check(true).success?# => trueThy::Boolean.check(false).success?# => true# TimeThy::Time.check(Time.now).success?# => trueThy::Time.check(0).success?# => false# DateTimerequire'date'Thy::DateTime.check(DateTime.now).success?# => trueThy::DateTime.check(0).success?# => false# nilThy::Nil.check(nil).success?# => trueThy::Nil.check(0).success?# => false

Parameterized types

# ArrayThy::Array(Thy::Integer).check([1,2,3]).success?# => trueThy::Array(Thy::String).check(%w[hihellosup]).success?# => true# HashThy::Hash({name: Thy::String,age: Thy::Integer,}).check({name: 'Bob',age: 18}).success?# => true# MapThy::Map(Thy::Symbol,Thy::Integer).check({a: 1,b: 2}).success?# => true# VariantThy::Variant(Thy::Integer,Thy::Float).check(3.14).success?# => trueThy::Variant(Thy::Integer,Thy::Float).check(3).success?# => true# EnumThy::Enum('USD','EUR').check('EUR').success?# => true# OptionThy::Option(Thy::String).check('a string').success?# => trueThy::Option(Thy::String).check(nil).success?# => true# InstanceOfclassA;endclassB < A;endclassC;endThy::InstanceOf(A).check(B.new).success?# => trueThy::InstanceOf(A).check(C.new).success?# => false# ClassExtendingThy::ClassExtending(A).check(B).success?# => trueThy::ClassExtending(A).check(C).success?# => false

Other types

# UntypedArrayThy::UntypedArray.check(1,'string',3.14).success?# => true# UntypedHashThy::UntypedHash.check({a: 1,b: 'c',1=>true}).success?# => true

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/akxcv/thy.

License

The gem is available as open source under the terms of the MIT License.

About

A minimal, strict runtime type system for Ruby

Topics

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages