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
There is more information about why Sorbet uses the |
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.
|
|
|
See Method Signatures. |
|
|
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)
|
|
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. |
|
|
See Type Aliases. |
|
|
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.