TypeScript学习笔记1
目录
简介
类型声明
类型推断
TS数据类型
常用数据类型
any
unknown
never
void
简介
TS是JS的扩展语言,是JS的超集,TS包含了JS的所有内容,再此基础上,TS增加了静态类型检查、接口、泛型等内容,在实际运行时,TS需要编译为JS,然后交给浏览器或其他的JS环境运行。
随着时代的发展,JS的应用越来越广泛,但由于JS设计初期,它的定位是一种简洁的脚本语言,这导致在实际应用时,JS会产生一些问题:不够清除的数据类型(由于JS没有类型校验,在实际使用时,可能会产生数据定义和使用时被看成两种类型,导致报错,而这种错误有时候很难排查)、可能会在代码编写过程中访问不存在的属性(如果访问了对象中不存在的属性,JS不会产生报错)、存在低级的拼写错误、有漏洞的逻辑(当代码中存在逻辑错误时,有时JS并不会报错,比如如果if else逻辑里存在不可能执行的逻辑,JS不会给任何提示)等等问题。
基于JS的种种问题,TS可以解决,TS提供静态类型检查(在代码运行之前进行的错误检查),不需要执行代码,当代码写错时,就会直接在IDE中报错。
对于同样的功能,TS的代码量要大于JS,但TS解构清晰,易于维护。
TS编译方法
1.命令行编译
TS文件以.ts结尾,由于.ts文件并不能被直接识别,需要将.ts文件编译成.js,才能运行。
安装TS后(npm i typescript),通过tsc命令可以编译.js文件(tsc 要编译的文件名,tsc是TypeScript Compiler的简写)。
2.自动化编译
执行tsc --init,会生成一个tsconfig.json配置文件,在这个文件中,可以配置ts文件如何转化为js文件,可以在内部设置将ts文件转换为js的哪种版本、是否启用严格模式等等。
配置好后,敲tsc --watch 表示监视ts文件,当被监视的文件变化时,就能生成js文件。如果只执行tsc --watch,则监控所有文件,如果需要监控某个文件,使用tsc --watch 文件名 来进行。
在默认配置下,即使ts文件报错,修改后也会更新Js文件,如果希望ts文件报错时不更新js文件,可以在tsconfig.json文件里设置noEmitOnError:true(发生错误时不要转换)。
3.脚手架编译
如果是使用的脚手架创建项目,ts文件会基于webpack/vite配置进行处理。此时一般不需要自己进行配置,项目会自动进行ts文件的编译工作。
类型声明
变量类型声明
在TS中,当定义了一个变量时,需要定义变量的类型:
let a: string
在声明变量类型时,推荐使用小写格式,且在: 后面最好要跟一个空格。
当定义变量a是string类型之后,如果在后续编码时,将非string类型赋值给a,则会导致报错。
函数类型声明
类型声明可以使用在变量定义时,也可以使用在函数参数上:
function add(a: number, b: number):number{return a+b
}
在声明函数时,通过在参数后面接: 类型,可以规定参数的类型。在function ()后面接: 类型,可以规定函数返回值的类型。
在定义后,调用函数时,必须传递对应数量对应类型的参数,否则就会引发报错。
字面量类型声明
let a: 'hello'
直接给变量规定一个字面量,表示该变量的值必须是这个字面量,也就是只能a = "hello",否则会引发报错。
类型推断
TS可以根据写的代码推断出变量类型,
比如先写了:
let a = 1
TS就会推断变量a的类型是number,当把a赋值成其他类型时,就会引发报错。
虽然TS会进行类型推断,但还是推荐在定义变量时进行类型声明,尽量不要让TS推断类型。
类型声明的大写和小写形式:
实际上,let a: string和let a: String是有区别的,对于小写的string,如果通过new String()给变量a赋值,是会产生错误的,小写的string规定变量只能存储基本类型的字符串,不能存储String()包装对象。而对于用大写String定义的变量,可以写基础类型,也可以写new String()。虽然大写的String更灵活,但是会导致更高的内存使用,再加上new String这种形式一般很少使用,一般不建议写大写的形式。
原始类型:number string boolean等原始类型
包装对象:Number String Boolean等复杂类型,内存占用率高,但可以实现自动装箱。
自动装箱:对于一个string变量,string本身是不会有.length属性的,在调用string变量的.length属性时,JS会将原始类型包装成对象,以调用对象的方法或属性。
也就是说:
let str = 'hello'str.length 时 会发生:
let size = (function(){//自动装箱,创建String对象包装原始字符串let tempStringObject = new String(str)//通过包装的对象,获取.length属性let lengthValue = tempStringObject.length//销毁临时对象,返回lengthreturn lengthValue}
)()
TS数据类型
在TS中,除了JS的数据类型:
string、number、boolean、null、undefined、bigint、symbol、object(Array、Function、Date、Error等),
TS还增加了新类型:any、unknown、never、void、tuple、enum
TS还新增了用于自定义类型的方式type、interface
常用数据类型
any
表示变量可以是任何类型
let a: any
当把变量类型设置成any时,也就代表放弃了对变量的类型检查。之后变量a存储任何类型,都不会引发报错。而且,当给变量赋值之后,TS不会进行类型推断,可以给a前后赋值不一样的类型。
如果在定义变量时,没有设置类型声明,则变量自动赋予的是any
let a
相当于 let a: any
any的问题:
1.对于any,由于any类型的变量可以赋值给任何类型的变量,可能会导致已经设置的变量类型声明失效:
let a: number
let b: any
b = false
a = b
此时不会报错,a的变量类型设置失效,a会变成false
2.对于any,读取any类型的任何属性,都不会报错
let a
a = 'a'
a.cat
虽然变量a身上没有cat属性,但是由于变量a的类型是any,也不会引发报错
因此要尽量少使用any,因为any会破坏别的变量的类型声明
unknown
unknown表示未知类型,适用于一开始不知道变量类型的场景,这时候,变量也不会进行类型推断,变量的类型也可以赋予各种类型。
但是,不同的是,unknown是一种更安全的any,any可以赋值给别的变量,会破坏别的变量的类型声明,但是unknown不会。
let a: unknowna = 1
a = 'a'
a = falselet b: stringb = a
会引发报错,因为最后a的类型是布尔,但b是字符串
实际上,如果最后a的类型是字符串,b也是字符串,在进行b=a时也会报错,因为TS认为a的类型是unknown,也就是不知道,所以无法将不知道的类型赋值给字符串类型,如果想取消这种报错,可以通过一些其他的逻辑,确保赋值的时候a一定是字符串,就可以不引发报错:
let a: unknowna = 1
a = 'a'let b: stringb = a
会引发报错,因为a的类型是unknown,但b是字符串通过下列方式可以不引发报错:
if(typeof a === 'string'){b = a判断当a的类型是string时才赋值,此时a的类型一定是string,可以通过静态检查
}可以通过断言:
b = a as string
或者
b = <string>a
<>也是一种断言的形式
对于any类型,访问不存在的属性时,不会引发报错,但是unknown类型访问不存在的属性时会报错:
let a: unknown
a = 'a'
a.cat
变量a身上没有cat属性,会引发报错
实际上,对于unknown,.任何属性都会引发报错,如果想避免报错,可以通过断言进行:
let a: unknown
a = 'a'
(a as string).length
never
never表示变量任何值都不是,也就是变量不能赋予任何值。
let a: never
定义之类,不能给变量a赋值任何属性。
基于这种特性,never一般并不会设置给变量,如果变量的类型是never,一般是TS主动推断出来的(比如逻辑到达不了的时候):
let a: string
a = 'a'
if(typeof(a)==='string'){console.log(a)
}else{这个分支永远到达不到,内部的a就是neverconsole.log(a)
}
never一般用于函数的返回值设定,表示函数没有返回值。
function fun():never{当函数没有return时,会默认返回undefined,这时候会报错
}
对于函数返回值是never的情况,函数不能返回数据,也就是返回never的函数不能具有可访问的终结点:如果函数递归调用,且永远在执行没有返回值时,不会报错;函数内部抛出了错误,不会执行完成时,也不会报错。
function fun():never{throw new Error('error')
}
或者
function fun():never{fun()
}
never一般很少使用。
void
表示空类型。通常用于函数返回值声明。表示函数不返回任何值,调用者也不依赖函数返回值进行任何操作。
void可以接收undefined。
function fun(a: string):void{console.log(a)
}fun('hello world')
当函数没有返回值时,函数默认返回undefined,void可以接收undefined,不会引发报错function fun():void{return
}
也返回undefined,不会引发报错或者直接显示返回undefined,也可以
function fun():void{return undefined
}
但给函数返回值声明为void和undefined并不相同,void有不能依赖函数返回值的特性,而undefined没有。
function func():void{}let res = func()
console.log(res)
到这里不会报错,但是如果操作res
比如:if(res)
会引发报错,因为void时,不能依赖返回值进行操作,但如果函数返回值是undefined,不会引发报错