学习TypeScript

大家好,欢迎和我一起来到 Typescript 的世界,开启一个新世界的大门,这一章主要来由浅入深的学习 Typescript。
大家都知道我们要学习的 Vue3 现在完全是使用 Typescript 进行重写的,不仅仅是 Vue,还有很多耳熟能详的大项目都使用了 Typescript,比如说 Angular 这个 google 出品的大而全的框架,ant-design 阿里出品的 React 组件库,Nativescript,Mobx,Nestjs 等等都完全使用 Typescript 进行开发。首先我们先介绍一下本章的脉络。

什么是 Typescript

动态类型语言(运行时才会检查数据类型):js,python

静态类型语言(书写时就会检查数据类型):c,c++,java,ts

为什么使用TypeScript
  • 程序更容易理解
  • 效率更高
  • 更少的错误

程序更容易理解(解决了js的两个问题:函数或者方法输入输出的函数类型,外部条件的等不清楚
动态语言本身的约束:需要运行过程中手动调试,效率高,在不同的代码块和定义中进行跳转,代码自动补全
,更少的错误,编译期间能够发现大部分错误,杜绝一些比较常见的错误,非常好的包容性,完全兼容js,第三方库可以单独编写类型文件
缺点:增加了学习成本,短期内增加了开发成本

全局安装TypeScript
npm install -g typescript

使用 tsc 全局命令:

// 查看 tsc 版本
tsc -v
// 编译 ts 文件
tsc fileName.ts
数据类型及定义

7种原始数据类型:Boolean,Number,Null,Undefined,Number,Bigint,Symbol(es6)

引用类型:boject

any可以更改任何数据类型,是万金油类型

总结:

  • Boolean
  • Null
  • Undefined
  • Number
  • String

特殊的 any 类型

Array 数组类型

Tuple 元祖

  • 元祖的表示和数组非常类似,只不过它将类型写在了里面 这就对每一项起到了限定的作用
let a:string = 'tyc'
let b:boolean = false
let c:number = 3
let d:number = null//null和undefined是所有数据类型的子类型
let e:any = '3'//any可以更改任何数据类型
//数组
let array:number[] = [2,1,3]//声明数组的类型只能为数字
//元祖类型
let user :[string,number] = ['你好',2]//类型不能错,源和目标数量要一致
user.push(2,2)//push可以不断进行不断添加,但是要在类型范围内
Interface接口

对对象的形状进行描述

Duck Typing(鸭子类型)

interface Person{
    readonly id :number,//只读属性
    name:string,
    age:number,
    salary?:number //?可选可不选
}
let viking:Person = {
    id:956,
    name :'tc',
    age:24,
}
viking.id = 12//报错.不允许修改
Function函数

限定函数的输入和输出

function add(x:number,y:number,z?:number){
   if(typeof z === 'number'){
    return x+y+z
   }else{
    return x+y
   }
}
//ts中:后面的对象都是在声明数据类型
add(1,2,2)
interface Isum{
    (a:number,b:number,c:number):number
}

//let add2:(a:number,b:number,c:number)=>number=add
let add2:Isum =add
add2(2,3,4)

类型推论 - 没有明确的指定类型的时候推测出一个类型

联合类型 - 表示类型或的关系

类型断言 - TypeScript 类型断言用来告诉编译器你比它更了解这个类型

  • 不是类型转换,断言成一个联合类型中不存在的类型是会出现错误的

类型守卫 - 当遇到一个联合类型的时候,使用条件语句,它可以自动帮你来缩小类型的范围

  • typeof 和 instanceof 关键字
//type inference
let str = 'str'
str =123//报错
//union types 联合类型
let numberOrString:number | string
numberOrString.toString //访问两者共有的方法
function getLength(input:string|number):number{
    const str = input as string
    if(str.length){
        return str.length
    }else{
        const number = input as number
        return number.toString().length
    }
}
//type guard 遇到联合类型可以缩小类型范围
function getLength2(input:string|number):number{
    if(typeof input == 'string'){
        return input.length
    }else{
        return input.toString().length
    }
}
枚举(enums)

枚举值分为两种 const常量值和计算值computed

以下都是常量值

enum Direction {
    up,
    down,
    left,
    right
}
console.log(Direction.up)//0 返回的下标
console.log(Direction.down)//1
console.log(Direction[0])//up

也可以给枚举项手动赋值

enum Direction {
    up=10,//此时以下的枚举项就会进行递增
    down,
    left=6,
    right//此时right的枚举项就是7

常量枚举
 const enum Direction {
    up ='up',
    down ='down',
    left ='left',
    right = 'right'
}
const value = 'up'
//假如value是res得到的数据
if(value == Direction.up ){
    console.log('goUp')
}
泛型(Generics)

泛型:定义时不指定类型,使用时才指定类型
泛型支持多个联用

function echo<T>(arg:T):T{ //传入什么值就返回什么值
    return arg
}
const result  = echo(2)

function swap<T,U>(tuple:[T,U]):[U,T]{
    return [tuple[1],tuple[0]]
}
const result2 = swap(['1','冯昕'])

泛型约束

通过 extends 关键字来设置约束条件,而不是想传入啥就传入啥

泛型和数组联用:T[]
泛型和接口联用: 使用extends关键字继承接口

interface IWithLenght{
    length:number
}
function echoWithArrLenght<T extends IWithLenght>(arg:T):T{
    console.log(arg.length)
    return arg
}
const str = echoWithArrLenght('123')
const obj = echoWithArrLenght({length:2,width:10})
let  arr2 = echoWithArrLenght([1,2,3])
泛型在类和接口的使用
class Queue<T>{
    private data = [];
    push(item:T){
        return this.data.push(item)
    }
    pop():T{
        return this.data.shift()
    }
}
const queue =new Queue<number>()
queue.push(1)
queue.push('str')//不能将string类型的值赋给number
console.log(queue.pop().toFixed())
console.log(queue.pop().toFixed())

interface KeyPari<T,U>{
    key:T,
    value:U
}
let kp1:KeyPari<number,string> = {key:250,value:'冯昕'}
let kpl2:KeyPari<string,string[]> = {key:'对象',value:['钟无艳','张飞']}//U:声明数组里面的元素是字符串
泛型总结

一、创建一个拥有特定类型的容器,比如:class 和interface上的泛型仿佛给你一个容器贴标签一样,比如:

let arrTwo:Array<number>=[1,2,3]

给这个数组贴了一个number的标签,告诉arrTwo,是一个装满number类型的数组或者是装着数字的队列

二、灵活约束参数的类型,传入的参数必须是xx方法xx属性,否则就会报错

三、函数的使用,函数的类型推断不会流入到函数体内,所以使用表达式没法建立类型的绑定,用泛型可以打破这个鸿沟

类型别名(type aliase),字面量,交叉类型

用type重新定义各种类型的别名,类似快捷方式,交叉或者组合的时候考虑使用类型别名

let sum = function(x:number,y:number):number{
    return x+y
}
const result = sum(1,2)
//创建类型别名,相当于快捷方式
type PlusType =(x:number,y:number) =>number
let sum2 :PlusType //赋值类型
const  result2 =sum2(2,3)//这里只声明了类型,没有实现,在js中运行会报错
//创建联合类型别名
type StringOrNumber = string | number
let result3 : StringOrNumber
result3 = 1 //如果类型不是sring和number会报错
//字面量
const str:'冯昕' = '冯昕' //这里会报不能将类型冯2昕分配给类型'冯昕'
const number :1 = 1
type Directions ='UP' | 'Down' | 'left' | 'right'
let toWhere : Directions = 'UP'

// 交叉类型
interface  Iname {
    name:string
}
type Iperson = Iname & {age:number}
let person:Iperson = {name:'tc',age:24}

内置类型

partial 可以快速把某个接口类型中定义的属性变成可选的
Omit 让可以从另一个对象类型中剔除某些属性,并创建一个新的对象类

//global objects
const a :Array<number> = [1,2,3]//按住ctrl查看定义文件
const date = new Date()
date.getTime()
const reg = /abc/
reg.test('abc')

//build-in object
Math.pow(2,2)

// DOM and BOM
let body = document.body
let allLis = document.querySelectorAll('li')
allLis.keys()
document.addEventListener('click',()=>{
    console.log('tc')
})

// Utility Types
interface Iperson{
    name:string,
    age:number
}
let viking:Iperson = {name:"tc",age:22}
// Partial 类型为值为可选的,可传可不穿
type Ipartial = Partial<Iperson>//Iperson当做泛型传进去
let viking2:Ipartial = {name:'tc'}
//  Omit忽略某个属性,忽略name,只剩age
type Iomit = Omit<Iperson,'name'>
let viking3:Iomit ={age:22}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多看书少吃饭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值