Sorbet

Sorbet

  • Get started
  • Docs
  • Try
  • Community
  • GitHub
  • Blog

›Getting Started

Getting Started

  • Overview
  • Adopting Sorbet
  • Tracking Adoption
  • Quick Reference
  • Visual Studio Code
  • TypeScript ↔ Sorbet

Static & Runtime

  • Gradual Type Checking
  • Enabling Static Checks
  • Enabling Runtime Checks
  • RBI Files
  • CLI Quickstart
  • CLI Reference
  • Runtime Configuration

Troubleshooting

  • Troubleshooting
  • Why type annotations?
  • FAQ
  • Error Reference
  • Unsupported Ruby Features

Type System

  • sig
  • Type Annotations (non-sig)
  • T.let, T.cast, T.must, T.bind
  • Class Types (Integer, String)
  • Arrays & Hashes
  • Nilable Types (T.nilable)
  • Union Types (T.any)
  • Flow-Sensitivity (is_a?, nil?)
  • T.type_alias
  • Exhaustiveness (T.absurd)
  • T::Struct
  • T::Enum
  • T.untyped
  • Blocks, Procs, & Lambdas
  • Abstract Classes & Interfaces
  • Final Methods & Classes
  • Override Checking
  • Sealed Classes
  • T.class_of
  • T.self_type
  • T.noreturn
  • T.anything
  • T.attached_class
  • Intersection Types (T.all)
  • Generics
  • T::NonForcingConstants
  • Banning untyped

Editor Features

  • Language Server (LSP)
  • Server Status
  • LSP & Typed Level
  • Go to Definition
  • Hover
  • Autocompletion
  • Find All References
  • Code Actions
  • Outline & Document Symbols
  • Documentation Comments
  • Suggesting sigs
  • Highlighting untyped
  • sorbet: URIs

Experimental Features

  • Tuples
  • Shapes
  • Overloads
  • Requiring Ancestors
  • RBS Comments
Edit

TypeScript ↔ Sorbet Reference

Many people learning Sorbet for the first time come from a TypeScript background. We’ve built this quick reference table mapping some common TypeScript features to the corresponding feature in Sorbet. (This is not a document about automatically interoperating between Sorbet and TypeScript; it is merely provided for educational purposes.)

Note that Sorbet is not affiliated with TypeScript in any official way, and the information in this table may become out of date as TypeScript evolves independently of Sorbet. Please use the “Edit” button at the top of the page to help correct inaccuracies.

Also note that Sorbet features do not always map to an exactly equivalent TypeScript feature. Be sure to read the relevant Sorbet docs to learn more about the features Sorbet provides.

TypeScript Sorbet Notes
string String Ruby strings are represented by Class Types. All values in Ruby are instances of a particular class, including strings.
number Integer, Float, Numeric Ruby has separate classes for different numeric types. number in JavaScript is most closely Float in Ruby, but unlike in JavaScript, integers and floating-point numbers are not transparently compatible with each other. To convert between different types, Ruby provides various to_i and to_f methods. See the Ruby docs for more.
boolean T::Boolean (also: TrueClass, FalseClass) JavaScript has boolean true and false as a primitive boolean type. Ruby has true as an instance of the Ruby TrueClass class and false as an instance of the FalseClass class (these are normal Class Types). Sorbet then uses a Union Type to define a Type Alias called T::Boolean inside the sorbet-runtime gem.
string[] T::Array[String] There is more information about why Sorbet uses this syntax in Arrays, Hashes, and Generics in the Standard Library.
Record<KeyType, ValueType>
Map<KeyType, ValueType>
{[x: KeyType]: ValueType}
T::Hash[KeyType, ValueType]

TypeScript programs frequently use "objects" as maps of keys to values, so long as the keys are JS strings or symbols. In Ruby, objects are instances of classes, and do not generally support arbitrary key-value lookup.

For key-value mappings, Ruby uses the Hash class. This most closely resembles the Map class from JavaScript. Ruby Hash instances are created with {x: y} syntax like JavaScript objects, and as a result are much more common than JavaScript Map instances.

There is more information about why Sorbet uses the T:: prefix in front of Hash in Arrays, Hashes, and Generics in the Standard Library.

any T.untyped See T.untyped and Gradual Type Checking for more information.
noImplicitAny # typed: strict TypeScript uses the noImplicitAny command line flag to prevent accidentally inferring any at function boundaries. Sorbet instead uses Strictness Levels, which are controlled by comments that live at the top of individual files.
function f(
  x: number
): string {...}
sig do
  params(x: Integer)
  .returns(String)
end
def f(x); ...; end
See Method Signatures.
let myName: string = "Alice"
my_name = T.let("Alice", String)
Unlike in TypeScript, this will do both a static and runtime type check. See Type Annotations for more.
number | string T.any(Integer, String) Sorbet uses T.any(...) to declare Union types. Do not confuse this with TypeScript's any, which corresponds to Sorbet's T.untyped.
MyClass & MyInterface T.all(MyClass, MyInterface) Sorbet uses T.all(...) to declare Intersection types. Note that since Sorbet's type system is nominal (unlike TypeScript's structural type system), T.all typically only makes sense when at most one of the types is a class type (and the rest are modules/interfaces).
x?: string,
x: string | null
T.nilable(String) Ruby has only nil, while JavaScript has both null and undefined. See Nilable Types for more.
if (typeof x === "string"),
if (x instanceof Date)
if x.is_a?(String)
# or
case x
when String then # ...
end
All Ruby objects are instances of a class, so the comparison for JavaScript's typeof operator is replaced by is_a? in Ruby. See Flow-Sensitive Typing.
if (x == null) if x.nil? See Flow-Sensitive Typing.
type AorB = A | B
AorB = T.type_alias {T.any(A, B)}
See Type Aliases.
{
  x: number,
  y?: string,
}
class Thing < T::Struct
  prop :x, Integer
  prop :y, T.nilable(String)
end
Sorbet uses T::Struct subclasses where TypeScript uses what it calls object types.
let x = expr as Type x = T.cast(expr, Type) Unlike in TypeScript, this will do both a static and runtime type check. See Type Annotations for more.
let x = expr as any x = T.unsafe(expr) See Type Annotations for more.
Literal Types, like "foo" none Sorbet has no exact equivalent for TypeScript's literal types. Consider using Typed Enums instead.
x?.foo x&.foo This is built into Ruby (Sorbet is not required to use it). The feature is called "optional chaining" in TypeScript or "the safe navigation operator" in Ruby.
x!.foo T.must(x).foo See Type Assertions for more.
x ?? y x.nil? ? y : x TypeScript calls this feature "nullish coalescing". A close approximation in Ruby is x || y. Only nil and false are falsy in Ruby (meanwhile 0, '', NaN, etc. are falsy in TypeScript). Thus, x || y in Ruby behaves exactly like x ?? y in TypeScript unless x can be false. If x is false, x || y evaluates to y, while x ?? y evaluates to false. The closest approximation is to use a ternary operator.
unknown T.anything See T.anything for more.
never T.noreturn (in type annotation), T.absurd (as type assertion) See T.noreturn and Exhaustiveness (T.absurd) for more.
pet is Fish (Type Predicates) none Sorbet does not have anything like TypeScript's type predicates feature. Instead, consider using something like this approach.
Discriminated Unions Sealed Classes and Modules  

This table is unfortunately not exhaustive. If you were looking for something in this table but couldn’t find it, please either use the “Edit” button above to add it, or reach out to a member of the Sorbet team asking whether it can be updated.

← Visual Studio CodeGradual Type Checking →

Get started · Docs · Try · Community · Blog · Twitter