Module: T

Defined in:
lib/types/_types.rb,
lib/types/boolean.rb,
lib/sorbet-runtime.rb,
lib/types/runtime_profiled.rb,
lib/types/compatibility_patches.rb

Overview

From the static system, T::Utils::RuntimeProfiled is T.untyped.

But from the runtime system, it’s a random class (specifically, a class that normal programs currently don’t have any instances of).

Thus, T::Utils::RuntimeProfiled can be used to introduce runtime-only type errors. This seems like a bad idea, but it’s not. It can be used to gather runtime type information from running code via a custom T::Configuration handler.

This process has only ever been used at Stripe, and is likely to have rough edges. If you’ve managed to find your way here and you’re curious to try it, please chat with us on Slack. There are no docs.

See also: the –suggest-runtime-profiled flag to sorbet.

Defined Under Namespace

Modules: AbstractUtils, Array, CFGExport, CompatibilityPatches, Configuration, Enumerable, Enumerator, Generic, Hash, Helpers, Private, Profile, Props, Range, Set, Sig, Types, Utils Classes: InexactStruct, InterfaceWrapper, Struct

Constant Summary collapse

Boolean =

T::Boolean is a type alias helper for the common ‘T.any(TrueClass, FalseClass)`. Defined separately from _types.rb because it has a dependency on T::Types::Union.

T.type_alias(T.any(TrueClass, FalseClass))

Class Method Summary collapse

Class Method Details

.absurd(value) ⇒ Object

A way to ask Sorbet to prove that a certain branch of control flow never happens. Commonly used to assert that a case or if statement exhausts all possible cases.



201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/types/_types.rb', line 201

def self.absurd(value)
  msg = "Control flow reached T.absurd."

  case value
  when Kernel
    msg += " Got value: #{value}"
  end

  begin
    raise TypeError.new(msg)
  rescue TypeError => e # raise into rescue to ensure e.backtrace is populated
    T::Configuration.inline_type_error_handler(e)
  end
end

.all(type_a, type_b, *types) ⇒ Object

T.all(<Type>, <Type>, …) – matches an object that has all of the types listed



49
50
51
# File 'lib/types/_types.rb', line 49

def self.all(type_a, type_b, *types)
  T::Types::Intersection.new([type_a, type_b] + types)
end

.any(type_a, type_b, *types) ⇒ Object

T.any(<Type>, <Type>, …) – matches any of the types listed



28
29
30
# File 'lib/types/_types.rb', line 28

def self.any(type_a, type_b, *types)
  T::Types::Union.new([type_a, type_b] + types)
end

.assert_type!(value, type, checked: true) ⇒ Object

Tells the typechecker to ensure that ‘value` is of type `type` (if not, the typechecker will fail). Use this for debugging typechecking errors, or to ensure that type information is statically known and being checked appropriately. If `checked` is true, raises an exception at runtime if the value doesn’t match the type.



141
142
143
144
145
# File 'lib/types/_types.rb', line 141

def self.assert_type!(value, type, checked: true)
  return value unless checked

  Private::Casts.cast(value, type, cast_method: "T.assert_type!")
end

.cast(value, type, checked: true) ⇒ Object

Tells the typechecker that ‘value` is of type `type`. Use this to get additional checking after an expression that the typechecker is unable to analyze. If `checked` is true, raises an exception at runtime if the value doesn’t match the type.

Compared to ‘T.let`, `T.cast` is trusted by static system.



116
117
118
119
120
# File 'lib/types/_types.rb', line 116

def self.cast(value, type, checked: true)
  return value unless checked

  Private::Casts.cast(value, type, cast_method: "T.cast")
end

.class_of(klass) ⇒ Object

Matches any class that subclasses or includes the provided class or module



70
71
72
# File 'lib/types/_types.rb', line 70

def self.class_of(klass)
  T::Types::ClassOf.new(klass)
end

.enum(values) ⇒ Object

Matches any of the listed values



54
55
56
# File 'lib/types/_types.rb', line 54

def self.enum(values)
  T::Types::Enum.new(values)
end

.let(value, type, checked: true) ⇒ Object

Tells the typechecker to declare a variable of type ‘type`. Use like:

seconds = T.let(0.0, Float)

Compared to ‘T.cast`, `T.let` is checked by static system.

If ‘checked` is true, raises an exception at runtime if the value doesn’t match the type.



131
132
133
134
135
# File 'lib/types/_types.rb', line 131

def self.let(value, type, checked: true)
  return value unless checked

  Private::Casts.cast(value, type, cast_method: "T.let")
end

.must(arg) ⇒ Object

A convenience method to ‘raise` when the argument is `nil` and return it otherwise.

Intended to be used as:

needs_foo(T.must(maybe_gives_foo))

Equivalent to:

foo = maybe_gives_foo
raise "nil" if foo.nil?
needs_foo(foo)

Intended to be used to promise sorbet that a given nilable value happens to contain a non-nil value at this point.

sig T.nilable(A)).returns(A)



180
181
182
183
184
185
186
187
188
189
# File 'lib/types/_types.rb', line 180

def self.must(arg)
  return arg if arg
  return arg if arg == false

  begin
    raise TypeError.new("Passed `nil` into T.must")
  rescue TypeError => e # raise into rescue to ensure e.backtrace is populated
    T::Configuration.inline_type_error_handler(e)
  end
end

.nilable(type) ⇒ Object

Shorthand for T.any(type, NilClass)



33
34
35
# File 'lib/types/_types.rb', line 33

def self.nilable(type)
  T::Types::Union.new([type, NilClass])
end

.noreturnObject

Indicates a function never returns (e.g. “Kernel#raise”)



44
45
46
# File 'lib/types/_types.rb', line 44

def self.noreturn
  T::Types::NoReturn.new
end

.procObject

Creates a proc type



59
60
61
# File 'lib/types/_types.rb', line 59

def self.proc
  T::Private::Methods.start_proc
end

.reveal_type(value) ⇒ Object

A way to ask Sorbet to show what type it thinks an expression has. This can be useful for debugging and checking assumptions. In the runtime, merely returns the value passed in.



194
195
196
# File 'lib/types/_types.rb', line 194

def self.reveal_type(value)
  value
end

.self_typeObject

Matches ‘self`:



64
65
66
# File 'lib/types/_types.rb', line 64

def self.self_type
  T::Types::SelfType.new
end

.type_alias(type) ⇒ Object

Constructs a type alias. Used to create a short name for a larger type. In Ruby this is just equivalent to assignment, but this is needed for support by the static checker. Example usage:

NilableString = T.type_alias(T.nilable(String))

sig {params(arg: NilableString, default: String).returns(String)}
def or_else(arg, default)
  arg || default
end

The name of the type alias is not preserved; Error messages will be printed with reference to the underlying type.



91
92
93
# File 'lib/types/_types.rb', line 91

def self.type_alias(type)
  T::Utils.coerce(type)
end

.type_parameter(name) ⇒ Object

References a type paramater which was previously defined with ‘type_parameters`.

This is used for generic methods. Example usage:

sig
.type_parameters(:U)
.params(
  blk: T.proc.params(arg0: Elem).returns(T.type_parameter(:U)),
)
.returns(T::Array[T.type_parameter(:U)])
def map(&blk); end


107
108
109
# File 'lib/types/_types.rb', line 107

def self.type_parameter(name)
  T::Types::TypeParameter.new(name)
end

.unsafe(value) ⇒ Object

For the static type checker, strips all type information from a value and returns the same value, but statically-typed as ‘T.untyped`. Can be used to tell the static checker to “trust you” by discarding type information you know to be incorrect. Use with care! (This has no effect at runtime.)

We can’t actually write this sig because we ourselves are inside the ‘T::` module and doing this would create a bootstrapping cycle. However, we also don’t actually need to do so; An untyped identity method works just as well here.

sig T.untyped).returns(T.untyped)



159
160
161
# File 'lib/types/_types.rb', line 159

def self.unsafe(value)
  value
end

.untypedObject

Matches any object. In the static checker, T.untyped allows any method calls or operations.



39
40
41
# File 'lib/types/_types.rb', line 39

def self.untyped
  T::Types::Untyped.new
end