初识TypeScript
TypeScript是在JavaScript的基础上进行的拓展,它限制变量的类型,兼容所有支持js的平台,更利于代码的维护。
在vscode上运行ts
首先创建了一个文件夹用来记录学习ts的过程
第一步:在该文件夹下面运行npm init ,在当前目录创建一个package.json文件
第二步:运行npm install typescript -g,表示安装ts:-g表示对ts进行全局安装,可以省略掉
注意!ts不能直接运行,需要编译成js才能运行
在终端运行tsc 01.ts将ts文件进行编译生成js文件才能被执行
在这里变量a被限制为number类型,那么a就只能是number类型,如果赋值为其他类型则会报错,如图↓
但是01.js仍然会被编译出来,a=‘string’
为了照顾那些习惯使用js的开发者们,同时也为了更好的推广ts,因为这样写是符合js的语法的,ts作为js的延展,默认没有那么严格,当然我们可以通过之后的配置,严格要求编译过程。
细心的同学会发现,编译生成的js文件变量的声明方式由let变成了var,这可以通过配置选择语法,运行tsc–init,会生成一个tsconfig.json文件,修改target值为es6
我们每次写完一个ts文件,都需要手动tsc才能编译成对应的js文件,然后再在终端node对应生成的js文件,也太麻烦了!
终端执行 npm install ts-node -g,之后直接用 ts-node 01.ts,就可以直接输出,==这时ts就不会再继续编译生成js文件了。==01## 一、ts的类型声明
1、声明一个变量,并指定类型,那么给该变量赋值的类型就不能是其他的类型;
2、如果变量的声明和赋值是同时进行的,ts会自动识别变量类型,不需人为声明;
这里ts会认为b的类型是boolean,所有给b赋值为number类型会报错
3、可以给函数的参数设定类型,更加严格,多一个少一个都不行,类型不一致也不行
function fn(a:number,b:number){
return a+b
}
console.log(fn(3,'2'))
//报错 TSError: ⨯ Unable to compile TypeScript:01.ts(8,18): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
4、给函数的返回值设置类型,格式:
(参数1,[参数2…]):返回值类型
function fn(a:number,b:number):number{//指定返回值的类型是number
return a+b
}
console.log(fn(3,2))
ts将js的动态性转变成ts的静态性,避免一些未知的错误发生!
这里提一下tsconfig.json配置文件里面的参数含义:
{
“compilerOptions”: {——编译器的配置
“target”: “esnext”,——ts代码要编译成哪个版本的js:es5、es6等等
“module”: “esnext”,——模块的规范es5、es6等等
“outDir”:“./dist”,——用来指定文件编译后所在的目录
“outFile”:“./dist/app.js”——所有全局作用域的代码会合并到一个文件中
“allowJs”:true,——是否编译js文件
“checkJs”:true,——是否检查js文件也必须符合ts的规范
“removeComments”:true——是否移除注释
“noEmitOnerror”:true——当有错误时不生成编译后的文件
“noImplicitAny”:true——不允许隐式的any
“strict”:true——所有的严格限制都打开
“moduleResolution”: “node”,
“importHelpers”: true,
“jsx”: “react”,
“esModuleInterop”: true,
“sourceMap”: true,
“baseUrl”: “.”,
“paths”: {
“@/": [
"src/”
]
},
“allowSyntheticDefaultImports”: true,
“experimentalDecorators”: true
}
}
二、 ts中的类型
前面已经讲了string,number,boolean三种类型,我们从第四个开始介绍:
- 字面量:类似常量,一旦确定就不能修改
let b:2
b=3//报错TSError: ⨯ Unable to compile TypeScript:01.ts(11,1): error TS2322: Type '3' is not assignable to type '2'.
也可以使用|来连接多个类型——(联合声明)
let c:'true'|'false'
c='false'
c='true'
//用的比较多的是对变量的类型的声明
let c:number|string
c=8
c='9'
//以上都不会报错
- any :表示任意类型,相当于关闭了ts的类型检测
let b:any ——显式any
let b ——隐式any
//这两种变量b都是any类型,实际项目中不建议用,这不和js没区别了嘛!
但是如果我们真的是不知道究竟是什么类型怎么办呢?用下面方式 ↓ - unknown:表示未知类型的值
以下讲解unknown和any在用法上的区别
let anyb:any
anyb=1
anyb=true
anyb='aa'
let unknownb:unknown
unknownb=2
unknownb=true
unknownb='bb'
let e:string
e=anyb// anyb不仅霍霍自己,还霍霍别人,这时候e变成了anyb最后一个赋值的值所属的类型:string
console.log(typeof e)//string
unknownb='string'
let p:string
p=unknownb//unknownb只霍霍自己,虽然上面对unknownb进行赋值:unknownb='string',但是并不能代表unknownb是string类型,它仍然是unknown类型,不能赋值给p,所以会报错:Type 'unknown' is not assignable to type 'string'.
console.log(typeof p)
unknown类型的变量就是安全的any类型,它不能直接赋值给其他类型的变量
如果非要赋值,我们可以
1、进行类型判断:typeof
2、类型断言,用来告诉解析器变量的实际类型
语法:变量 as 类型——方式一
<类型>变量——方式二
p=unknownb as string//类型断言方式一
p=<string>unknownb//类型断言方式二
总之尽量不用any,用unknown代替any
- void:用来表示空,主要用来设置函数返回值的类型,表示空值
当函数没有返回值的时候,默认就是void
如图,将鼠标放到声明的函数上面,会显示void
如果我们写了返回值,编译器会自动识别返回值类型,如图
如果设置函数的返回值是void,那么你就不能返回其他类型的值,否则会报错,除了undefined
function fn():void{
// return true 报错
// return 不报错
// return null 报错Type 'null' is not assignable to type 'void'
return undefined //不报错
}
- never:表示永远都不会返回结果
function fn2():never{
throw Error('报错了')
}
- object:表示一个js对象
-let b:object
-let b:{ }
这两方式都是声明对象类型的变量,但是更提倡第二个,因为object类型的太多了,函数,数组都是对象
{ }用来指定对象中可以包含哪些属性
语法:
{属性名:属性值} ,这种语法属性个数必须保持一致
{属性名:属性值},在属性名后面加上?表示可选的属性
let obj:{name:string,age?:number}
obj={name:'mm'}
obj={name:'mm',age:25}
但是如果我们并不知道到底有哪些属性时候,可以这样设置:
[propName:string]:any——任意类型任意个数的属性
let obj:{name:string,[propName:string]:any}
obj={name:'mm'}
obj={name:'mm',age:25}
obj={name:'mm',age:25,gender:'male'}
设置函数结构的类型声明
语法:(形参:类型,形参:类型…)=>返回值类型
let fn3:(a:number,b:number)=>number
fn3=function(n1,n2){
return n1+n2
}
- 数组的类型声明
语法:
方式一:类型[ ]
方式二:Array<类型>
//方式一
let arr:number[]
arr=[1,2]
arr=[1,2,'o']//报错
//方式二
let arr2:Array<number>
arr2=[2,3]
arr2=[2,3,true]//报错
- 元组:就是固定长度的数组TS中新增类型
语法:【类型,类型,类型…】
let tuple:[string,number]
tuple=['ok',6]
- enum枚举,适合于在多个值之间进行选择的时候设置TS中新增类型
语法: enum 定义枚举类型
enum Gender{
male=0,//这里是等号,别和对象混淆了,对象里面是冒号
female=1
}
let people:{name:string,gender:Gender}
people={
name:'胖虎',
gender:Gender.male//方便我们清楚的知道是男是女而不用纠结是0还是1
}
console.log(people.gender===Gender.female)
类型别名,用来简化类型的使用
语法:type 类姓名=…
type p=1|2|3|4|5
let pp:p
pp=3
pp=4
interface 和 type 的区别
写法上: interface不写等于,type要写;
可扩充性:interface是非闭合的,可以扩充(除非加上严格的签名类型),但是type不可以;
继承性:interface可以继承(extend),还可以继承class,因为class也是有类型的,type没有继承,但是可以通过类型交叉(&)来合并type,一旦合并的类型有冲动,结果为never;
同名合并:interface可以实现同名合并,type不可;