1.认识TypeScript
TypeScript是JS的一个超集,在原有的语法基础上,添加强类型并切换为基于类的面向对象语言
2.为什么要用TypeScript?
(让代码更加严谨)
①.js宽松的类型约束在大型项目中会带来非常多的安全隐患
②.TS在开发时就能给出编译错误,而JS错误则需要在运行时 能暴露。
③.作为强类型语言,你可以明确知道数据的类型。代码可读性极强,几乎每个人都能理解。
④.TS非常流行,现在技术都支持ts
3.安装
//安装命令(全局环境)
npm install typescript -g
//查看版本
tsc -v
tsc xxx.ts
//安装ts-node
npm install ts-node -g
//另外ts-node需要依赖 tslib 和 @types/node 两个包:
npm install tslib @types/node -g
//现在,我们可以直接通过 ts-node 来运行TypeScript的代码:
ts-node math.ts
(注意:webpack上的直接脚手架就ok了!)
4.TS的基本数据类型
①string
let msg:string = "xiaobai"
同时也支持ES6的模板字符串来拼接变量和字符串
②number
TypeScript和JavaScript一样,不区分整数类型(int)和浮点型(double),统一为number类型
let num:number = 12
ES6新增了二进制和八进制的表示方法,而TypeScript也是支持二进制、八进制、十六进制的表示
//其他进制表示
num = 100; //十进制
num = 0b110; //二进制
num = 0o555; //八进制
num = 0xf23; //十六进制
③boolean类型
let isLogin:boolean = true;
isLogin = false;
④null和undefined类型
let n:null = null;
let u:undefined = undefined;
⑤symbol类型
const s1:symbol = Symbol("title")
const s2:symbol = Symbol("title")
⑥array
const arr1: string[] = ["a","b"];
const arr2: Array<string> = ["a","b"]; //不推荐这种,因为react的jsx里面组件就是<>,有冲突
⑦object类型
const obj1:object = {
name:"coder",
age:"18"
}
⑧any类型
let mes:any = 123;
mes = "coder";
mes = true;
let arr: any[] = ["coder",18,1.88];
⑨unknown类型(描述类型不确定的变量)
function foo():string{
return 'foo'
}
function bar():number{
return 123
}
const flag = true
let res:unknown
if(flag){
res = foo()
}else{
res = bar()
}
⑩void类型
函数是没有返回值,返回void
function sum(num1:number,num2:number):void {
console.log(num1+num2)
}
⑪never类型
never 表示永远不会发生值的类型,比如一个函数:
如果一个函数中是一个死循环或者抛出一个异常,那么这个函数会返回东西吗?
不会,那么写void类型或者其他类型作为返回值类型都不合适,我们就可以使用never类型;
function loopFun():never {
while(true){
console.log('123')
}
}
function loopErr():never{
throw new Error()
}
function handleMessage(message: number|string){
switch(typeof message){
case 'string':
console.log('123')
break
case 'number':
console.log('456')
break
default:
const check:never = message
}
}
⑫tuple类型
元组类型,里面可以放不同数据类型
let arr1: [string,number,number] = ["coder",18,1.88];
const item1 = arr1[0] //coder 并且知道是string类型
- 元组类型和数组类型的区别
** 数组中通常建议存放相同类型的元素,不同类型的元素是不推荐放在数组中。(可以放在对象或者元组中)
** 元组中每个元素都有自己特性的类型,根据索引值获取到的值可以确定对应的类型;
const info:(string|number)[] = ['jim',18,1.88]
const item1 = info[0] //不能确定类型
const tinfo: [string,number,number] = ['jim',18,1.88]
const item2 = tinfo[0] // 一定是string
元组类型的应用场景
tuple通常可以作为返回的值,在使用的时候会非常的方便
function useState<T>(state:T):[T,(newState:T) => void] {
let currentState = state
const changeState = (newState:T) => {
currentState = newState
}
return [currentState,changeState]
}
const [counter,setCounter] = useState(10)
⑬枚举类型enum
枚举其实就是将一组可能出现的值,一个个列举出来,定义在一个类型中,这个类型就是枚举类型;
枚举允许开发者定义一组命名常量,常量可以是数字、字符串类型
enum Direction {
LEFT,
RIGHT,
TOP,
BOTTOM
}
function turnDirection(direction:Direction){
switch(direction) {
case Direction.LEFT:
console.log('转向左边')
break;
case Direction.RIGHT:
console.log('转向右边')
break;
case Direction.TOP:
console.log('转向上边')
break;
case Direction.BOTTOM:
console.log('转向下边')
break;
default:
const myDirection:never = direction
}
}
枚举类型的值
// 数字型枚举 - 默认从0开始,依次递增
enum Score {
BAD, // 0
NG, // 1
GOOD, // 2
PERFECT, // 3
}
let score: Score = Score.BAD;
// 字符串类型枚举
enum Score {
BAD = 'BAD',
NG = 'NG',
GOOD = 'GOOD',
PERFECT = 'PERFECT',
}
// 反向映射
enum Score {
BAD, // 0
NG, // 1
GOOD, // 2
PERFECT, // 3
}
let scoreName = Score[0]; // BAD
let scoreVale = Score["BAD"]; // 0
// 异构
enum Enum {
A, // 0
B, // 1
C = 'C',
D = 'D',
E = 8,
F, // 9
}
// 面试题:异构类型每一项的枚举值 => js本质实现(手写一个异构枚举的实现)
let Enum;
(function (Enum) {
// 正向
Enum["A"] = 0;
Enum["B"] = 1;
Enum["C"] = "C";
Enum["D"] = "D";
Enum["E"] = 8;
Enum["F"] = 9;
// 逆向
Enum[0] = "A";
Enum[1] = "B";
Enum[8] = "E";
Enum[9] = "F";
})(Enum || (Enum = {}))
5.对象类型
function printXY(point:{x:number,y:number}) {
console.log(`x坐标:${point.x};y坐标:${point.y}`)
}
printXY({x:12,y:88});
6.可选类型
function printXY(point:{x:number,y:number,z?:number}) {
console.log(`x坐标:${point.x};y坐标:${point.y}`)
if(point.z){
console.log("z坐标:",point.z)
}
}
printXY({x:12,y:88});
printXY({x:12,y:88,z:55});
可选类型可以看做是 类型 和 undefined 的联合类型
function print(message?:string){
console.log(message)
}
print()
print('123')
print(undefined)
print(null) // error
7.联合类型
function printId(id:number|string){
if(type id == "string"){
console.log("我的id是:",id.toUpperCase())
}else{
console.log("我的id是:",id)
}
}
printId(12);
printId{"abc"}
8.交叉类型
在开发中,我们进行交叉时,通常是对对象类型进行交叉的
interface Colorful {
color: string
}
interface IRun {
running: ()=> void
}
type NewType = Colorful & IRun
const obj:NewType = {
color:'red',
running:function(){}
}
9.函数的参数返回类型
function aaa(num1:number,num2:number):number{
return num1+num2
}
通常情况下不需要返回类型注解,因为TypeScript会根据 return 返回值推断函数的返回类型
匿名函数的参数与函数的声明会有一点不同:
- 当一个函数出现在ts可以确定该函数会被如何调用的地方时;
- 该函数的参数会自动指定该类型;
const names = ['abc','cba','nba']
names.forEach(item => {
console.log(item.toUpperCase())
})
我们并没有指定item的类型,但是item是一个string类型:
- 这是因为ts会根据forEach函数的类型以及数组的类型推断出item的类型;
- 这个过程称之为上下文类型,因为函数执行上下文可以帮助确定参数和返回值的类型