一、前言
TypeScript开发中需要对定义的变量指定类型,目前版本都支持哪些类型,每一个类型都有哪些含义,在这篇文章中,我们将会对其进行总结说明
二、JavaScript基本数据类型以及TypeScript特有的数据类型。 JS基本数据类型: String、Number、null、undefined、Boolean、SymbolTS特有的数据类型:任意类型(any)、元组类型(tuple)、枚举类型(enum)、void类型、Never类型、never类型、数组类型(Array)、类型断言(Type Assertion)、接口类型(interface)、函数类型(Function)具体分别含义如下
2.1 JavaScript(JS)基本数据类型包括: 数字(Number):表示整数和浮点数,如 1、-2、3.14 等。字符串(String):表示文本数据,用单引号(')或双引号(")括起来,如 ‘hello’、“world” 等。布尔值(Boolean):表示真或假,只有两个值,true 和 false。null:表示空值,即没有任何值的变量。undefined:表示未定义,即变量声明了但没有赋值。Symbol:表示唯一的标识符,通常用于对象属性的键名。注意,JS 还有一种复杂数据类型,即对象(Object),它可以包含多个属性,每个属性是一个键值对。对象的属性可以是基本数据类型或其他对象,甚至可以是函数。
2.2 TypeScript 特有的数据类型包括: 任意类型(any):表示可以是任何类型。元组类型(tuple):表示有限数量的未知类型元素的数组。枚举类型(enum):表示具有命名值的一组相关的常量。void类型:表示没有任何类型,常用于函数的返回值类型。never类型:表示永远不存在的值的类型。unknown类型:表示任何类型的值,但在使用前必须先进行类型检查。类型断言(Type Assertion):表示在某些情况下需要手动告诉编译器变量的类型。接口类型(interface):表示对象的类型。函数类型(Function):表示函数的类型。注意: node 不能直接执行 TypeScript 文件,需要先将 TypeScript 编译成 JavaScript,然后再执行 JavaScript 代码运行。
三、类型实践 3.1 String、Number、null、undefined、Boolean、Symbol类型声明JavaScript常规写法
let myName = "suwu150";let count = 1;let a = null;let b = undefined;let visiable = false;const nameShow = Symbol("foo");TypeScript写法如下:
不能更改赋值给它们的变量类型,否则会直接报错
let myName: string = "suwu150";let count: number = 1;let a: null = null;let b: undefined = undefined;let visiable: boolean = false;const nameShow: unique symbol = Symbol("foo");编译后的结果:
"use strict";let myName = "suwu150";let count = 1;let a = null;let b = undefined;let visiable = false;const nameShow = Symbol("foo");注意,这个结果是在官方在线演练场中编译后的结果,有些老铁可能会在本地终端使用tsc进行验证,会发现运行结果和我这个不一致,这是因为 tsconfig.json中配置如下:
{"compilerOptions": {"target": "ES5", }}在体验了正常定义之后,我们体验下,定义的类型和赋值类型有所差异的情况下,会有如下提示,继续编写TypeScript代码
let myName: string = "suwu150";let count: number = 1;let a: null = null;myName = 2023;count = '平平安安'a = 888继续编译看结果
3.2 元组类型(tuple)JavaScript数组和TypeScript数组之间的区别
JS中的数组可以是字符串、数字等其他类型的数据,而TS中的数组是纯数字类型(number)的集合,如果在TS中定义包含多个类型的数组,那就是元组。
JS写法如下:
let arr = ['语文','数学']TS声明数组有多种方式,具体如下:
(1)数组的数据类型一致 Array<>:声明一个数组,数组类型为<>中定义的类型,比如:Arraystring[] 声明一个数组,数组类型为[]前定义的类型,比如number[]//声明一个数组,并且数组中的数据类型都是字符串let arr:Array<string> = ['语文','数学'] let arrA:string[] = ['语文','数学'] //注意:数组这样写会报错let arr:Array= ['语文','数学'] //error (2)数组的数据类型不一致 联合数据声明:比如(string|number)[],声明一个数组,数组类型为字符串、数字。数组中数据的类型可以不随定义的类型位置的限定。let arr:(string|number)[] = ['a',1]let arrB:(string|number)[] = ['a',1,1,'b']let arrC:(string|number)[] = [1,1,'b','c']let arrC:(string|number)[] = [1,1]//或者这样声明let arrD: Array<string | number> = [1, 12, 'a'] (3)数组的数据类型任意数组内包含多种类型
let arr:any[] = ['a',1,true,null]//或者这样声明let arrE:Array<any> = ['a',1,true,null] (4)限制类型和长度的元祖数组tuple(元祖):是固定数量的不同类型的元素的组合,比如[number, string]。数组中数据的位置、类型以及个数必须要和声明的类型、声明类型的位置、声明类型的个数保持一致,否则就会报错。
let tupleArr: [number, string] = [1, '数学']let tupleArrA: [number, string] = [1, '数学',1]//errorlet tupleArrA: [number, string] = ['数学',1]//error 3.3 枚举类型(enum)枚举主要分为数字类型枚举、字符串类型枚举、异构。 语法:enum + 变量名,意思是定义了一个叫做“变量名”的枚举类型 优点:定义一些常量,可以清晰地表达意图或创建一组有区别的用例。
(1)数字型枚举 含义:枚举成员都是number类型,如果没有对枚举对象中的枚举成员赋值,那么会默认从枚举对象中的第一个枚举成员的值是0,并依次递增。具有以下特点:反向映射
枚举成员的值可以不用初始化
enum Value {A,B,C,D,E,F}let value: Value = Value['A']let valueName = Value[0]console.log(value)//0console.log(valueName)//A以上可知,我们既可以取到枚举成员的属性名,也能取到枚举成员的属性值,它们之间是相互映射的。
修改枚举成员的默认值
enum Value {A,B,C=8,D,E,F}let value: Value = Value['E']let valueNameA = Value[8]let valueNameB = Value[9]console.log(value)//10console.log(valueNameA) //Cconsole.log(valueNameB) //Dconsole.log(Value['A']) //0console.log(Value['B']) //1console.log(Value['C']) //8console.log(Value['D']) //9console.log(Value['E']) //10以上TypeScript内容编译后结果我们能够清楚地看到,其实在赋值之前还是按照0序号开始,当有指定索引时才按照指定的排序
"use strict";var Value;(function (Value) {Value[Value["A"] = 0] = "A";Value[Value["B"] = 1] = "B";Value[Value["C"] = 8] = "C";Value[Value["D"] = 9] = "D";Value[Value["E"] = 10] = "E";Value[Value["F"] = 11] = "F";})(Value || (Value = {}));var value = Value['E'];var valueNameA = Value[8];var valueNameB = Value[9];console.log(value); //10console.log(valueNameA); //Cconsole.log(valueNameB); //Dconsole.log(Value['A']); //0console.log(Value['B']); //1console.log(Value['C']); //8console.log(Value['D']); //9console.log(Value['E']); //10 (2)字符串类型枚举含义:枚举成员类型都是字符串 需要注意以下几个方面:
字符串枚举没有反向映射,如果进行反向映射的话,取得的值时undefined;
字符串枚举没有递增,需要对每一个字符串枚举类型成员进行赋值,即必须具有初始化表达式
enum StringValue {A = 'A',B = 'B',C = 'C',D = 'D',E = 'E',F = 'f'}let stringValueVal = StringValue['A']console.log(stringValueVal)//A以下是错误示范,不能对字符串类型枚举进行反向映射
let stringValueNameA = StringValue['f']let stringValueNameB = StringValue[0]console.log(stringValueNameA)//undefinedconsole.log(stringValueNameB)//undefined (3)异构含义:枚举类型包括字符串类型和数字类型
注意:含有字符串值成员的枚举中也可以使用计算值。
enum Enum {A,B,C = 'C',D = 'd',E = 9,F}console.log(Enum['10'])//Fconsole.log(Enum['C'])//Cconsole.log(Enum['A'])//0console.log(Enum['d'])//undefinedconsole.log(Enum['D'])//dconsole.log(Enum[9])//Econsole.log(Enum[0])//A以上就是一个典型的异构,包含字符串和数字类型值。
同时注意,含有字符串成员值的枚举中允许使用计算值。
enum Count {A = 12 * 2,B = 24 * 2}console.log(Count['A']) // 24console.log(Count['B']) // 48这种写法没问题,即可以使用计算值,也可以包含字符串值。
enum Count {A,B = 24 * 2,C = 'c-suwu150',D = 48 * 2,}console.log(Count['A']) // 0console.log(Count['B']) // 48console.log(Count['C']) // c-suwu150console.log(Count['D']) // 96 (4)枚举成员的值的两种形式-计算值和常量枚举对象中成员的value有两种形式,计算值或者常量,怎么区分是计算值和常量呢?我们可以通过枚举成员表达式来判断,只要是枚举成员是表达式则为常量。枚举成员表达式的判断条件如下:
枚举表达式字面量(主要是字符串字面量或数字字面量)对之前定义的常量枚举成员的引用带括号的常量枚举表达式一元运算符 ++、 –常量枚举表达式是二元运算符 + 、-、*、/、%、<<、>>、&、|、^的操作对象。注意:如果求值后值为NaN或Infinity,那么会在编译阶段报错。 3.4 任意类型(any)声明变量类型为any时
编译时会绕过所有类型的检测,直接通过编译阶段的检查
可以任意访问属性的方法和属性
any类型可以赋值给任意类型
如果变量初始没有定义类型,默认为any;经过赋值后,TS会根据赋值类型来标识变量的类型
let anyValue: any = 1;//修改变量类型anyValue = true;//赋值给任意类型,比如boolean,之后再赋值,就只能赋值boolean类型,否则异常let booleanValue: boolean = anyValue;console.log(booleanValue)//true注意: any类型在使用过程中就像一个潘多拉魔盒,即使使用了断言,也丧失了在静态类型检查阶段发现错误的可能性。
3.5 unknow(未知类型)声明变量类型为unknow时
unknown类型只能赋值给any和unknown类型,any类型可以赋值给任意类型
let unknownValue: unknown;//对变量进行任意赋值unknownValue = true;unknownValue = 'sss';unknownValue = 1;//赋值给unknown类型的变量let testValue1: unknown = unknownValue;//赋值给any类型的变量let testValue2: any = unknownValue;//赋值给boolean类型的变量,报错,因为unknown类型只能赋值给unknown、anylet testValue3: boolean = unknownValue;//报错 3.6 void(空类型)声明对象类型为void时
返回为空值
function func(): void { }只能将它赋值为 undefined 和 null,因此在定义函数的返回值为void时,也可return undefined/null
let voidValue1: void = undefined;let voidValue2: void = null; 3.7 never(不存在的值类型)never类型表示永不存在的值的类型。具有以下特点:
never类型是所有类型的子类型,即never类型可以赋值给任何类型。其他任何类型均不是never类型的子类型,即其他类型均不可赋值给never类型,除了never本身。即使any类型也不可以赋值给never类型。返回类型为never的函数中,其终点必须是不可执行的,例如函数过程中抛出了错误或者存在死循环。变量也可以声明为never类型,但其不能被赋值设置变量类型为never,表示永远不能执行完或者永远Error,具体示例如下:
函数中出现了死循环,永远不能执行完,因此其函数类型为:() => never
function infiniteLoop(): never {while (true) { }return 'over'}函数中出现报错,不会执行到return over,因此其函数类型为:() => never
function errFunc(): never {throw new Error()return 'over'}以上就是类型声明和应用,感兴趣的同学帮忙来个点赞关注,谢谢。