Better inference for literal types
String, numeric and boolean literal types (e.g. "abc"
, 1
, and true
) were previously inferred only in the presence of an explicit type annotation.Starting with TypeScript 2.1, literal types are always inferred for const
variables and readonly
properties.
The type inferred for a const
variable or readonly
property without a type annotation is the type of the literal initializer.The type inferred for a let
variable, var
variable, parameter, or non-readonly
property with an initializer and no type annotation is the widened literal type of the initializer.Where the widened type for a string literal type is string
, number
for numeric literal types, boolean
for true
or false
and the containing enum for enum literal types.
Example
const c1 = 1; // Type 1
const c2 = c1; // Type 1
const c3 = "abc"; // Type "abc"
const c4 = true; // Type true
const c5 = cond ? 1 : "abc"; // Type 1 | "abc"
let v1 = 1; // Type number
let v2 = c2; // Type number
let v3 = c3; // Type string
let v4 = c4; // Type boolean
let v5 = c5; // Type number | string
Literal type widening can be controlled through explicit type annotations.Specifically, when an expression of a literal type is inferred for a const location without a type annotation, that const
variable gets a widening literal type inferred.But when a const
location has an explicit literal type annotation, the const
variable gets a non-widening literal type.
Example
const c1 = "hello"; // Widening type "hello"
let v1 = c1; // Type string
const c2: "hello" = "hello"; // Type "hello"
let v2 = c2; // Type "hello"