变量和数据类型

JavaScript虽说深受万千程序员喜爱,却有着对于企业大规模开发很难管理的缺陷。这时候,TypeScript的优势便体现出来。接下来,我们会先接触在TypeScript中定义变量相关的问题。之后再来了解JavaScript类型在TypeScript中的变化以及TypeScript中新增的类型。希望这些内容可以帮助你对typescript更加了解。

一. 变量声明方式

1.1. 声明变量的格式

我们已经强调过很多次,在TypeScript中定义变量需要指定 标识符 的类型。

所以完整的声明格式如下:

/
/

标识符: 数据类型 = 赋值;

比如我们声明一个message,完整的写法如下:  

  • 注意:这里的string是小写的,和String是有区别的
  • string是TypeScript中定义的字符串类型,String是ECMAScript中定义的一个类
message: 
 = 
;


message = 
; 


message = 
;

1.2. 声明变量的关键字

在TypeScript定义变量(标识符)和ES6之后一致,可以使用var、let、const来定义:

myname: 
 = 
;

 myage: 
 = 
;

 myheight: 
 = 
;

但是,我们会发现使用var关键字会有一个警告:

typescript 取得类型 typescript 类型声明_typescript 取得类型

var关键字警告

可见,在TypeScript中并不建议再使用var关键字了,主要原因和ES6升级后let和var的区别是一样的,var是没有块级作用域的,会引起很多的问题,这里不再展开探讨。

所以,在之后的开发中,我们定义变量主要使用let和const

1.3. 变量的类型推断

在开发中,有时候为了方便起见我们并不会在声明每一个变量时都写上对应的数据类型,我们更希望可以通过TypeScript本身的特性帮助我们推断出对应的变量类型:

message = 
;

上面的代码我们并没有指定类型,但是message实际上依然是一个字符串类型:

typescript 取得类型 typescript 类型声明_数据类型_02

给message赋值一个number

这是因为在一个变量第一次赋值时,会根据后面的赋值内容的类型,来推断出变量的类型:

  • 上面的message就是因为后面赋值的是一个string类型,所以message虽然没有明确的说明,但是依然是一个string类型
message = 
; 


 age = 
; 


 isFlag = 
;

1.4. 声明name报错

我们在TypeScript的文件中声明一个name(很多其他的名字也会)时,会报错:

typescript 取得类型 typescript 类型声明_string类_03

声明name报错信息

主要错误信息:

无法重新声明块范围变量“name”

我们前面明明(明明说管我什么事)没有声明name,但是却说我们重复声明了

  • 这次是因为我们的typescript 将 DOM typings 作为全局的运行环境;
  • 所以当我们声明 name时, 与 DOM 中的全局 name 属性出现了重名;

typescript 取得类型 typescript 类型声明_赋值_04

name的声明位置

如何解决这个问题呢?

  • 有两种方案:去掉DOM typings 的环境和声明模块

方式一:删除DOM typings的环境

但是这种办法对于我们来说并不合适,因为我们依然希望在DOM下编译我们的TypeScript代码

typescript 取得类型 typescript 类型声明_typescript 取得类型_05

 

删除DOM typing

方式二:声明我们的ts文件为一个模块

既然与全局的变量出现重名,那我们将脚本封装到模块(module)中,因为模块有属于自己的作用域,就不会和全局的产生冲突:

  • 在Typescript 中,我们可以使用ES6的export来导出一个对象,并且该文件被视为module
name = 
;


 {};

1.5. console.log报错

另外为了测试方便我们经常使用console.log来进行测试,但是使用时会报一个警告:

console.log警告

这个时候,我们可以配置

typescript 取得类型 typescript 类型声明_数据类型_06

配置tslint

:

二. JavaScript数据类型

2.1. number类型

数字类型是我们开发中经常使用的类型,TypeScript和JavaScript一样,不区分整数类型(int)和浮点型(double),统一为number类型。

num = 
;

num = 
;

num = 
;

如果你学习过ES6应该知道,ES6新增了二进制和八进制的表示方法,而TypeScript也是支持二进制、八进制、十六进制的表示:

num = 
; 


num = 
; 


num = 
; 


num = 
;

2.2. boolean类型

boolean类型只有两个取值:true和false,非常简单

flag: 
 = 
;

flag = 
;

flag = 
 > 
;

2.3. string类型

string类型是字符串类型,可以使用单引号或者双引号表示:

  • 注意:如果打开了TSLint,默认情况下推荐使用使用双引号
message: 
 = 
;

message = 
;

同时也支持ES6的模板字符串来拼接变量和字符串:

name = 
;

 age = 
;

 height = 
;


 info = 
;

.log(info);

2.4. array类型

数组类型的定义也非常简单,有两种方式:

  • 但是TSLint会推荐我们使用上面这种方式
names1: 
[] = [
, 
, 
];

 names2: 
<
> = [
, 
, 
];

2.5. object类型

object对象类型可以用于描述一个对象:

myinfo: object = {

  name: 
,

  age: 
,

  height: 
,

};

但是上面的代码会报一个警告:

typescript 取得类型 typescript 类型声明_赋值_07

 

object定义后警告

这是因为TSLint建议我们所有的key按照字母进行排序,但是这个并不是特别有必要,我们还是可以关闭掉:

typescript 取得类型 typescript 类型声明_数据类型_08

 

关闭TSLint字母排序

:

属性是不可以访问的

如果我们访问myinfo中的属性,会发现报错:

typescript 取得类型 typescript 类型声明_数据类型_09

 

找不到name属性

这是因为TypeScript并不知道某一个object类型上面就有一个name的属性。

但是如果我们让它是类型推断的,就可以正常的访问:

  • 这是因为推导出来的类型,是如下的类型

myinfo的类型

还有一种方法是定义后面会学到的接口,TypeScript一个非常好用的特性就是接口interface,后续我们会进行非常详细的学习

2.6. symbol类型

在ES5中,如果我们是不可以在对象中添加相同的属性名称的,比如下面的做法:

person = {

  identity: 
,

  identity: 
,

}

通常我们的做法是定义两个不同的属性名字:比如identity1和identity2。

但是我们也可以通过symbol来定义相同的名称,因为Symbol函数返回的是不同的值:

s1 = Symbol(
);

 s2 = Symbol(
);


 person = {

  [s1]: 
,

  [s2]: 
,

};

这是Symbol的一个用法,更多其他用法大家可以自行学习,或者等到后续确实需要用到时,我们再详细讲解。

2.7. null和undefined

在JavaScript 中,undefined 和null 是两个基本数据类型。

在TypeScript中,它们各自的类型也是undefined和null,也就意味着它们既是实际的值,也是自己的类型:

n: 
 = 
;

 u: 
 = 
;

三. TypeScript数据类型


TypeScript在原有的JavaScript基础上引入了很多好用的类型:enum枚举类型、tuple元组类型、any类型、void类型、never类型等

 

3.1. enum类型

3.1.1. 枚举的基本定义

枚举类型在很多语言都有的类型,比如C++、Java等等,并且也非常好用,所以TypeScript引入了enum类型,让我们开发更好的方便和安全。

枚举类型通常是定义一组数据:

Direction {

  EAST,

  WEST,

  NORTH,

  SOUTH,

}


 d1 = Direction.EAST;

 d2 = Direction.NORTH;

3.1.2. 枚举类型的值

枚举类型有自己的值,比如打印上面的d1和d2

typescript 取得类型 typescript 类型声明_typescript 取得类型_10

打印d1和d2结果

默认情况下,枚举中的数据是从0开始的,我们可以改变它的初始化值,比如下面的代码:

Direction {

  EAST = 
,

  WEST,

  NORTH,

  SOUTH,

}


 d1 = Direction.EAST;

 d2 = Direction.NORTH;


.log(d1); 


.log(d2);

也可以全部自己来指定:

Direction {

  EAST = 
,

  WEST = 
,

  NORTH = 
,

  SOUTH = 
,

}


 d1 = Direction.EAST;

 d2 = Direction.NORTH;


.log(d1); 


.log(d2);

我们也可以通过对应的值去获取对应的数据名称:

.log(Direction[
]); 


.log(Direction[
]);

3.2. tuple类型

3.2.1. tuple的基本使用

tuple是元组类型,很多语言中也有这种数据类型,比如Python、Swift等。

tInfo: [
, 
, 
] = [
, 
, 
];

 item1 = tInfo[
]; 


 item2 = tInfo[
];

3.2.1. tuple和数组类比

初学tuple会觉得它和数组非常相似

但是数组中通常会定义一组相同的数据,如果数据不同会造成类型的丢失:

  • 注意:这里我使用了一种联合类型,后面会讲到
aInfo: 
<
|
> = [
, 
, 
];

 itema = aInfo[
];

3.3. any类型

在某些情况下,我们确实无法确定一个变量的类型,并且可能它会发生一些变化,这个时候我们可以使用any类型(类似于Dart语言中的dynamic类型)

a: 
 = 
;

a = 
;

a = 
;


 aArray: 
[] = [
, 
, 
];

3.4. void类型

void类型通常用于函数没有返回值时来使用:

  • 首先我们需要说明的是,在TypeScript中函数也是有类型的

下面的函数,虽然我们没有指定它的类型,但是它会通过类型推导出来:

sum = 
 {

  
 num1 + num2;

};




 sum: 

 = 
 {

  
 num1 + num2;

};

typescript 取得类型 typescript 类型声明_数据类型_11

 

sum函数的类型

如果一个函数没有返回值,那么它的返回值类型就是void

  • 我们可以将null和undefined赋值给void类型,也就是函数可以返回null或者undefined
sayHello: 

 = 
 {

  
.log(
 + name);

};

3.5. never类型

never类型表示一种从来不会存在的值的类型,有点绕,我们来这样理解:

  • 如果一个函数中是一个死循环,那么这个函数会返回东西吗?不会,那么写void类型或者其他类型作为返回值类型都不合适,我们就可以使用never类型。
  • 如果一个函数是抛出一个异常,那么这个函数是不是也没有返回值呢?这个时候我们也可以使用never类型。

死循环的函数抛出异常的函数

最后我想说的是,变量及数据类型犹如在茫茫TS宇宙中的一颗行星,想要更加深入了解TS,光看这些是远远不够的,如果你对此有兴趣,接下来我会分享更多关于TS的内容,当然你也可以自行研究,希望这些内容可以帮你在编程道路上更进一步。