This chapter describes the static type checking TypeScript provides for JavaScript statements. TypeScript itself does not introduce any new statement constructs.
Variable statements are extended to include optional type annotations.
VariableDeclaration: ( Modified )
Identifier TypeAnnotation(opt) Initialiser(opt)
VariableDeclarationNoIn: ( Modified )
Identifier TypeAnnotation(opt) InitialiserNoIn(opt)
TypeAnnotation:
: Type
A variable declaration introduces a variable with the given name in the containing declaration space. The type associated with a variable is determined as follows:
- If the declaration includes a type annotation, the stated type becomes the type of the variable. If an initializer is present, the initializer expression is contextually typed (section 4.19) by the stated type and must be assignable to the stated type, or otherwise a compile-time error occurs.
- If the declaration includes an initializer but no type annotation, and if the initializer doesn't directly or indirectly reference the variable, the widened type (section 3.9) of the initializer expression becomes the type of the variable. If the initializer directly or indirectly references the variable, the type of the variable becomes the Any type.
- If the declaration includes neither a type annotation nor an initializer, the type of the variable becomes the Any type.
Multiple declarations for the same variable name in the same declaration space are permitted, provided that each declaration associates the same type with the variable.
Below are some examples of variable declarations and their associated types.
var a; // any
var b: number; // number
var c = 1; // number
var d = { x: 1, y: "hello" }; // { x: number; y: string; }
var e: any = "test"; // any
The following is permitted because all declarations of the single variable x
associate the same type
(Number) with x
.
var x = 1;
var x: number;
if (x == 1) {
var x = 2;
}
In the following example, all five variables are of the same type, { x: number; y: number; }
.
interface Point { x: number; y: number; }
var a = { x: 0, y: <number> undefined };
var b: Point = { x: 0, y: undefined };
var c = <Point> { x: 0, y: undefined };
var d: { x: number; y: number; } = { x: 0, y: undefined };
var e = <{ x: number; y: number; }> { x: 0, y: undefined };
Expressions controlling if
, do
, and while
statements can be of any type (and not just type Boolean).
Variable declarations in for
statements are extended in the same manner as variable declarations in
variable statements (section 5.1).
In a for-in
statement of the form
for (Var in Expr) Statement
Var must be an expression classified as a reference of type Any or the String primitive type, and Expr must be an expression of type Any, an object type, or a type parameter type.
In a for-in
statement of the form
for (var VarDecl in Expr) Statement
VarDecl must be a variable declaration without a type annotation that declares a variable of type Any, and Expr must be an expression of type Any, an object type, or a type parameter type.
A continue
statement is required to be nested, directly or indirectly (but not crossing function
boundaries), within an iteration (do
, while
, for
, or for-in
) statement. When a continue
statement
includes a target label, that target label must appear in the label set of an enclosing (but not crossing
function boundaries) iteration statement.
A break
statement is required to be nested, directly or indirectly (but not crossing function boundaries),
within an iteration (do
, while
, for
, or for-in
) or switch
statement. When a break
statement includes a
target label, that target label must appear in the label set of an enclosing (but not crossing function
boundaries) statement.
It is an error for a return
statement to occur outside a function body. Specifically, return
statements are
not permitted at the global level or in module bodies.
A return
statement without an expression returns the value undefined
and is permitted in the body of
any function, regardless of the return type of the function.
When a return
statement includes an expression, if the containing function includes a return type
annotation, the return expression is contextually typed (section 4.19) by that return type and must be of a
type that is assignable to the return type. Otherwise, if the containing function is contextually typed by a
type T, Expr is contextually typed by T's return type.
In a function implementation without a return type annotation, the return type is inferred from the return
statements in the function body, as described in section 6.3.
In the example
function f(): (x: string) => number {
return s => s.length;
}
the arrow expression in the return
statement is contextually typed by the return type of f
, thus giving
type string
to s
.
Use of the with
statement in TypeScript is an error, as is the case in ECMAScript 5's strict mode.
Furthermore, within the body of a with
statement, TypeScript considers every identifier occurring in an
expression (section 4.3) to be of the Any type regardless of its declared type. Because the with
statement
puts a statically unknown set of identifiers in scope in front of those that are statically known, it is not
possible to meaningfully assign a static type to any identifier.
In a switch
statement, each case
expression must be of a type that is assignable to or from (section
3.8.4) the type of the switch
expression.
The expression specified in a throw
statement can be of any type.
The variable introduced by a catch
clause of a try
statement is always of type Any. It is not possible to
include a type annotation in a catch
clause.