Overview
TypeScript has had string literal types for a while. With TypeScript 2.0, the type system was extended by several new literal types:
- Boolean literal types
 - Numeric literal types
 - Enum literal types
 
TypeScript 2.1 improves the type inference for all of these types when a const variable or readonly property has a literal initializer.
Better Inference for const Variables
Let’s start with local variables and the var keyword. When TypeScript sees the following variable declaration, it infers the type string for the baseUrl variable:
 | 
 | 
The same goes for { 适用于 } variables declared with the let keyword:
 | 
 | 
Both variables are inferred to have type string because they can change at any time. They are initialized with a literal string value, but they can be modified later.
However, if a variable is declared using the const keyword and initialized with a string literal, the inferred type is no longer string, but the corresponding string literal type:
 | 
 | 
The inferred type should be as specific as possible since the value of a constant string variable can never change. It’s impossible for the baseUrl variable to hold any other value than "https://example.com/". This information is now reflected in the type system.
Literal type inference works for other primitive types, too. If a constant is initialized with an immediate { An immediate result, action, or reaction happens or is done without any delay } numeric or boolean value, a literal type is inferred as well:
 | 
 | 
Similarly, a literal type is inferred when the initializer is an enum value:
 | 
 | 
Note that direction is typed as FlexDirection.Column, which is an enum literal type. Had we used the let or var keyword to declare the direction variable, its inferred type would’ve been FlexDirection instead.
Better Inference for readonly Properties
Similar to local const variables, readonly properties with a literal initializer are inferred to be of a literal type as well:
 | 
 | 
Read-only class properties can only be initialized right away or from within a constructor. Attempting to change the value in other places results in a compile-time error. Therefore, it is reasonable { 合理的 } to infer a literal type for a read-only class property because its value doesn’t change (given that the TypeScript program is type-correct).
Of course, TypeScript can’t know what happens at run-time: properties marked with readonly can be changed at any time by some piece of JavaScript code. The readonly modifier is meant to restrict access to a property from within TypeScript code, but it has no run-time manifestation { 表现,显现 } at all. That is, it is compiled away and doesn’t show up in the generated JavaScript code.
Usefulness of Inferred Literal Types
You might ask yourself why it is useful to infer literal types for const variables and readonly properties. Consider the following code example:
 | 
 | 
If the HTTP_GET constant was inferred to have type string instead of "GET", you’d get a compile-time error because you wouldn’t be able to pass HTTP_GET as the second argument to the request function:
 | 
 | 
Of course, it’s not allowed to pass any arbitrary string as a function argument if the corresponding parameter only allows two specific string values. When the literal types "GET" and "POST" are inferred for the two constants, though, it all works out { If a situation works out well or works out, it happens or progresses in a satisfactory way }.
Next up: widening and non-widening literal types and the difference between the two.