In the previous article, we learned about the installation and use of TS and the basic types . This article continues to learn about type inference and variable declaration.
type inference
The core function of TS is that 类型检查
we need to add type annotations to variables or methods to indicate the data type. When no type annotation is provided, the TS compiler will use it 类型推断
to infer the type.
var num = 2; // 类型推断为 number
num = "12"; // 编译错误,不能将类型“string”分配给类型“number”
If the type cannot be inferred due to lack of declaration, then its type is assumed to be the default dynamic any
type .
Type assertion Type Assertion
In some cases, we will be clearer than TS The exact type can be used to 类型断言
manually specify the type of a value, which allows the variable to change from one type to another. It has no runtime impact, it just 编译阶段
works.
Type assertions come in two forms, the first is 尖括号
syntax:
<type> value
The second is as
the syntax :
value as type
for example:
// typescript
// 类型推断为 string
var str = '1'
// 成功,类型断言先转成any,再转成number
var str2: number = <number><any>str
// 失败,string直接转成number会报错
var str3: number = <number>str
// 编译为
// javascript
var str = '1';
var str2 = str;
From the above example, we can know that the use of type assertion conversion requires an association between the two types. For example, if string
it is any
a subset of , then they can be converted to each other, and if number
it is any
a subset of , then they can also be converted to each other, so they str2
can be successfully assigned ; but string
the number
two types do not sufficiently overlap to be convertible. Type assertions can only be used if the type is specified, and baseless assertions are dangerous.
variable declaration
The variable declaration methods of TS and JS are the same. Here is a brief introduction to the relationship and difference between var, let and const.
was
All the while, we use var
statements to declare an 函数范围
or 全局范围
variable.
// 全局范围
var a = 1;
function fn() {
// 函数范围
var message = "Hello, world!";
return message;
}
var has some strange properties, there is a feature called 变量提升
, no matter where you declare the variable, it will be processed before any code is executed:
function fn(flag) {
if (flag) {
var x = 10;
}
return x;
}
fn(true); // 10
fn(false); // undefined
The function fn above is equivalent to
function fn(flag) {
// 变量x的初始值为 undefined
var x;
if (flag) {
x = 10;
}
return x;
}
In TS, the above code adds verification, although it can still run, it will give a prompt
// typescript
function fn(flag: boolean) {
if (flag) {
var x = 10;
}
return x; // 报错:在赋值前使用了变量“x”
}
another example:
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[1](); // 输出10
This is because what is passed into the function during the loop 变量i
is 10 全局变量
after for
the loop ends, i
and the output of the calling function is 10.
In addition, using var can repeatedly declare the same variable without reporting an error:
var a;
var a;
var a;
let
Because of some problems var
with , ES6
a new let
statement . Except for the name difference, itlet
is written in the same way as .var
let hello = "Hello!";
When let
declaring a variable with , it uses the 块作用域
. Unlike variables var
declared which can be accessed outside their enclosing function, variables cannot be accessed outside 块作用域
their enclosing 块
or loop. for
Like the example above:
function fn(flag) {
if (flag) {
let x = 10;
}
return x;
}
fn(true); // 10
fn(false); // 报错:x is not defined
another example:
let a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[1](); // 输出1
Another characteristic of variables with block scope is that they cannot be 声明之前
read or written again.
// 报错:Cannot access 'a' before initialization
a++;
let a;
The above does not report an error saying a
undefined , but that it cannot be accessed before initialization. It means that the variable a exists in scope, but the area up to the code that declares it belongs to 暂时性死区
, so it cannot be accessed. In TS, the above code gets an error 声明之前已使用的块范围变量“a”
.
注意
At one point, we can still access a block-scoped variable before it is declared. It's just that we can't call that function before the variable declaration. The modern runtime throws an error if the generated code targets ES2015.
function foo() {
// 可以成功捕获到a
// 运行时会报错:Cannot access 'a' before initialization
return a;
}
// 不能在'a'被声明前调用'foo'
// 运行时应该抛出错误
foo();
let a;
The above code will not prompt and report an error in TS, so you need to pay attention.
As we mentioned above, var can be used for repeated declarations, but let is not so relaxed:
let a;
let a;
The above code reports an error at runtime: Identifier 'a' has already been declared
, and it will also prompt in TS 无法重新声明块范围变量“a”
that it can only be declared once in the same block scope.
It is not required that two declarations be block-scoped for TypeScript to give a false warning:
// case1
function f(x) {
// TS警告:标识符“x”重复
let x = 100; // 运行时报错:Identifier 'x' has already been declared
}
// case2
function g() {
// TS警告:无法重新声明块范围变量“x”
let x = 100;
var x = 100; // 运行时报错:Identifier 'x' has already been declared
}
If you want to declare a block-scope variable with the same name in function scope, you need to put it in a different block:
function fn(flag, x) {
if (flag) {
let x = 100;
return x;
}
return x;
}
fn(false, 0); // 0
fn(true, 0); // 100
The act of introducing a new name in a nested scope is called屏蔽
const
const
Statement is another way of declaring variables, which is similar to the way of let
declaring , the difference is that after declaring and assigning 不能重新赋值
:
const role = 'Tom'
// TS警告:无法分配到 "role" ,因为它是常数
role = 'Jerry'
The above code reports an error when running:Assignment to constant variable
The value of a const reference cannot be changed, but the internal state can be changed:
const person = {
name: 'Tom'
}
// 失败
person = {
name: 'Jerry'
}
// 成功
person.name = 'Jerry'
In general, let
it is close to the way of const
use , the basic principle is that if a variable does not need to be reassigned, it is used const
, and in other cases it is used let
.