typescript

一、 ts的简单认识

认识+深入理解+熟练使用

vue3支持ts

ts是微软开发的开源、跨平台编程语言。在2012年发布。作者是安德斯.海尔斯伯格(C#首席架构师)。

TS => { {ES} + interfaces + strongly types + generic(泛型)}

ES => { {JS} + proto types + dynamic types + constructor functions }

TS comfiles to JS ( brower can't run ts) ts编译器

TS是JS的超集

特点:

1. ts可以编译出纯净、简洁的js代码,并能够在所有浏览器、node环境和es3及以上的js引擎运行。

2. ts 强大的类型系统 js开发者可以使用高效的开发工具和常用操作(静态检查和代码重构)

3.ts提供最新的和不断发展的js属性。比如异步功能和decorator

二、安装ts

全局安装

yarn global add typescript

查看是否安装成功

tsc -V

三、编写ts代码

tsc手动编译

(()=>{
    function sayHi(str: string) {
        return '您好呀' + str
    }

    let text = '小甜甜'
    console.log(sayHi(text))
})()

// 浏览器可以运行ts文件,但是ts里面必须是js代码

// 用tsc编译ts,生成js文件,就可以在浏览器运行

// 生成的文件,被修饰的入参类型将去掉
// let修饰的变量,tsc编译后变成var修饰

自动编译

1. tsc --init 生成tsconfig.json

2.  tsconfig.json 内 将outDir 改成 './js'

     strict 改成false

3. 终端  运行任务 tsc监视

四、类型注解

一种 “轻量级的为函数或者变量添加的约束” 的方式

typescript 提供了静态代码分析能力,它可以分析代码结构和类型注解

五、接口

一种能力,一种约束

六、类

ts的类只是一个语法题,本质还是js实现的

七、webpack+ts

八、ts基础类型

// let 变量名: 变量类型 = 值
    let flag: boolean = true
    console.log(flag)

boolean\number\string

undefined\null 可以作为所有类型的子类型,undefined&null可以赋值给所有子类型

let numb: number = null

数组类型

// let 变量名: 数据类型[] = [值1,值2,值3] 
    let arr1: number[] = [1,2,3,4]
    console.log(arr1)

    // 泛型 let 变量名: Array<数据类型> = [值1,值2,值3] 
    let arr2: Array<number> = [7,8,9]
    console.log(arr2)

元组类型

    let arr3: [string,number,boolean] = ['Bonnie',1.051234,false]
    console.log(arr3[0].split(''))
    console.log(arr3[1].toFixed(2))

枚举

 // 枚举
    enum Color {
        red,
        green=9,
        blue
    }
    const color: Color = Color.red
    console.log(color)
    console.log(Color.red,Color.green,Color.blue)
    console.log(Color[0],Color[9],Color[10])

    enum Gender{
        女,
        男
    }
    console.log(Gender.女)

any类型

let any1: any = '~_~'
    any1 = 909
    console.log(any1)

    let any2: any[] = [100,'小妹妹',false]
    console.log(any2[1].split('')) 
    // console.log(any2[0].split('')) //编译不报错 浏览器报错

void类型

// void类型: 与any类型相反 代表没有任何类型
    function fn():void{
        console.log('小米米')
    }
    console.log(fn())

    let vv: void = undefined
    console.log(vv)

object: 非原始类型

 function fnn(obj:object):object{
        console.log(obj)
        return {
            name:'卡卡西',
            age:16
        }
    }
    console.log(fnn({}))
    console.log(fnn(new String('bilibl')))
    console.log(fnn(String))

联合类型,类型断言,类型推断

// 联合类型: 表示取值可以是多种类型之一
    function combine(o: number|string){
        // return o.toString()
        if((<string>o).length){
            return (o as string).length
        }else {
            return o.toString().length
        }
    }
    console.log(combine(12))
    console.log(combine('212'))

    // 类型断言: 告诉编译器 我知道我自己在做什么
    // 1. <类型>变量
    // 2. 变量 as 类型

    // 类型推断:TS会在没有明确的指定类型的时候推测出一个类型
    // let n = 124  // => number
    // n = 'aaa'
    // console.log(n)

    // let n // => any
    // n = 123
    // n = 'aaa'
    // console.log(n)

九、接口

接口: 对象的状态(属性)和行为(方法)的抽象
是一种规范 一种约束 一种功能

// 需求: 创建人的对象, 需要对人的属性进行一定的约束
// id是number类型, 必须有, 只读的
// name是string类型, 必须有
// age是number类型, 必须有
// sex是string类型, 可以没有

(()=>{
    interface IPerson{
        readonly id:number
        name:string
        age:number
        sex?:string
    }

    const person: IPerson = {
        id:1,
        name:'bonnie',
        age:17,
        sex:'女'
    }

    console.log(person)
})()

函数类型

// 为了使用接口表示函数类型,我们需要给接口定义一个调用签名。
// 它就像是一个只有参数列表和返回值类型的函数定义。
// 参数列表里的每个参数都需要名字和类型。
(()=>{   
    interface SearchFunc {
        // 定义一个调用签名
        (source:string, subString:string): boolean
    } 

    const fn: SearchFunc = function (source:string, subString:string): boolean {
        return source.search(subString) > -1
    }

    console.log(fn('我是Bonnie','我'))

})()

类类型

用接口约束类

一个类可以实现多个接口

类与类是继承(extends) 接口与类是实现(implements)

// 类类型: 用接口约束类
// 一个类可以实现多个接口
// 类与类是继承(extends) 接口与类是实现(implements)
(()=>{
    interface IFly {
        fly()
    }
    interface ISwim {
        swim()
    }
    interface IFlyAISwim extends IFly,ISwim{}

    class Person implements IFlyAISwim{
        fly(){
            console.log('fly')
        }
        swim(){
            console.log('swim')
        }
    }

    // class Person1 implements IFly,ISwim{
    //     fly(){
    //         console.log('fly')
    //     }
    //     swim(){
    //         console.log('swim')
    //     }
    // }
    const person = new Person()
    person.fly()
    person.swim()

})()

十、类

// 类: 模板 通过模板实例化对象
// 面向对象编程思想
(()=>{
    // ts中类的定义
    class Person {
        // 属性
        name: string
        age: number
        gender: string

        // 构造方法: 初始化对象属性
        constructor(name: string='Bonnie',age: number=18,gender: string='girl'){
            this.name = name
            this.age = age
            this.gender = gender
        }

        // 实例方法
        sayHi(str: string) {
            console.log(`my name is ${this.name},i'm ${this.age} & i'm a ${this.gender},${str}`)
        }
    } 

    const person = new Person()
    person.sayHi('马萨赛季')
})()

继承

// 类与类之间的继承关系
// A继承了B
// A => 子类 -> 派生类 
// B => 基类 -> 超类(父类)

// 继承用extends
// 子类用super继承父类的构造器,属性,方法
// 子类可以重写父类 
(()=> {
    class Person {
        name: string
        age: number

        constructor(name:string='人', age:number=0){
            this.name = name
            this.age = age
        }

        sayHi(str: string){
            console.log(`哇哇哇,${str},我是${this.name}`)
        }
    }

    class Student extends Person{
        constructor(name:string, age:number) {
            super(name,age)
        }

        // 重写
        sayHi() {
            console.log('i"m student')
            super.sayHi('嘟嘟嘟')
        }
    }

    const person = new Person()
    console.log(person)
    person.sayHi('ccc')
    const stu = new Student('Bonnie',16)
    console.log(stu)
    stu.sayHi()

})()

多态

父类的引用指向子类的对象  不同类型的对象针对相同方法,产生不同的行为

(()=>{
    class Animal {
        name: string
        constructor(name: string){
            this.name = name
        }
        run(distance:number=0){
            console.log(`${this.name}跑了${distance}米`)
        }
    }

    class Dog extends Animal{
        constructor(name: string){
            super(name)
        }
        run(distance:number=5){
            console.log(`${this.name}跑了${distance}米`)
        }
    }

    class Pig extends Animal {
        constructor(name: string){
            super(name)
        }
        run(distance:number=10){
            console.log(`${this.name}跑了${distance}米`)
        }
    }

    const ani: Animal = new Animal('动物')
    const dog: Animal = new Dog('狗')
    const pig: Animal = new Pig('猪')

    ani.run()
    dog.run()
    pig.run()

    const dog1: Animal = new Dog('gou')
    const pig1: Animal = new Pig('zhu')
    dog1.run()
    pig1.run()

    function showRun(ani: Animal){
        ani.run()
    }

    console.log('==========')
    
    showRun(dog1)
    showRun(pig1)
})()

修饰符

// 修饰符:修饰类内部属性成员的可访问性
// 类的属性方法构造器 默认用public修饰
// public -- 公共类 修饰的成员 任何位置都能访问
// private -- 私有类 修饰的成员 在类外部不能访问, 子类也无法访问
// protected -- 受保护类 修饰的成员 在类外部不能访问, 子类可访问
(()=>{
    class Person {
        public name: string
        // private name: string
        // protected name: string
        public constructor(name: string){
            this.name = name
        }
        public eat(){
            console.log(this.name,'eat')
        }
    }
    class Stu extends Person{
        constructor(name: string){
            super(name)
        }
        public eat(){
            console.log(this.name,'eat')
        }
    }
    const person = new Person('bonnie')
    console.log(person.name)
    person.eat()
    const stu = new Stu('andy')
    console.log(stu.name)
})()

readonly修饰符

// readonly修饰符:  readonly修饰的属性成员,在外部无法修改,只可读; 
// 在类内部的普通函数也无法修改;只能在构造函数内部进行赋值
(()=>{
    // class Person {
    //     readonly name: string = 'moren'
    //     constructor(name:string){
    //         this.name = name
    //     }
    //     changeName(){
    //         this.name = 'xxx'
    //     }
    // }

    // const p1 = new Person('bonnie')
    // p1.name = 'ccc'
    // console.log(p1.name)

    // readonly修饰构造器的参数,该类就有了一个只读的属性成员,外部可访问但无法修改
    // 使用public private protected修饰构造器的参数,该类就有了一个或公共或私有或受保护的属性成员

    class Person {
        constructor(public name:string){
            this.name = name
        }
    }

    const p1 = new Person('bonnie')
    p1.name = 'ccc'
    console.log(p1.name)
})()

存取器

存取器:在类中,对类中的属性进行有效的控制  通过getter setter进行实现

(()=>{
    class Person {
        firstName: string
        lastName: string

        constructor(firstName:string, lastName:string){
            this.firstName = firstName
            this.lastName = lastName
        }
        
        get fullName(){
            console.log('get....')
            return this.firstName+'_'+this.lastName
        }

        set fullName(val){
            console.log('set....',val)
            const n = val.split('_')
            this.firstName = n[0]
            this.lastName = n[1]
        }

    }

    const p = new Person('上官','婉儿')
    console.log(p.fullName)
    p.fullName = '薛_宝钗'
    console.log(p.fullName)
})()

静态成员

// 静态成员: 用static修饰的类的属性或者方法 
// 静态成员 不能通过实例对象访问 需要通过 类.静态属性 进行访问 
// 静态方法 需要通过 类.静态方法 进行访问
(()=>{
    class Person {
        // static name 报错   静态属性“name”与构造函数“Person”的内置属性函数“name”冲突。
        static name1: string = '贾宝玉'
        constructor() {
            // this.name1 = name1
        }
        static say(){
            console.log('i"m ',Person.name1)
        }
    }
    const p = new Person()
    console.log(p)
    // p.say()
    // console.log( p.name1)
    // console.log(Person.name1)
    Person.say()
})()

抽象类

// 抽象类:abstract 包含抽象方法(一般没有任何功能的具体实现)不能实例化抽象类 只能给子类实例化和让子类实现内部的抽象方法
// 抽象类服务于派生类
(()=>{
    abstract class Animal {
        
        abstract eat()

        // 报错 astract标记的抽象类,不能有代码的实现
        // abstract eat(){}

        sayHi(){
            console.log('hi')
        }
    }

    // 不能实例化抽象类
    // const dog = new Animal()

    class Dog extends Animal {
        eat() {
            console.log('汪汪 骨头')
        }
    }

    const dog = new Dog()
    dog.eat()  // 抽象类的实现
    dog.sayHi() //调用抽象类的实例方法

})()

十一、函数

// 函数: 重复代码的整合 功能的实现
(()=>{
    // 函数声明 命名函数
    function add(x: string, y: string): string {
        return x+y
    }

    // 函数表达式 匿名函数
    let add2 = function (x: number, y: number): number {
        return x+y
    }

    console.log(add('a','b'))
    console.log(add2(1,2))

    // ts函数完整写法
    let add3:(x: number, y: number)=> number = function (x: number, y: number): number {
        return x+y
    }
    console.log(add2(99,88))

})()

默认参数、可选参数

// 默认参数 若不传,默认某个值
// 可选参数 ?修饰的参数 可传可不传

(()=>{
    function showName(firstName:string='贾',lastName?:string){
        return firstName+'_'+lastName
    }
    console.log(showName('雪','抱柴'))
})()

剩余参数

// 剩余参数(rest参数)
// 在函数声明的时候,只能放在所有参数的最后
(()=>{
    function add (n1: number,n2: number,...ns:number[]): void{
        console.log(n1)
        console.log(n2)
        console.log(ns)
    }
    add(1,2,3,4,5,5)
})()

函数重载声明

// 函数重载 名字相同 参数返回值不同
(()=>{
    // 函数重载声明
    function add(x:number,y:number): number
    function add(x:string,y:string): string
    function add(x:number|string,y:number|string){
        if(typeof x === 'number' && typeof y === 'number')
        return x+y
        else if (typeof x === 'string' && typeof y === 'string')
        return x+y
    }
    console.log(add(1,4))
    console.log(add('1','4'))
    // console.log(add(1,'4'))
    // console.log(add('1',4))
})()

十二、泛型

 泛型:在定义函数、接口、类时不确定使用的数据类型,只有在使用函数、接口、类时才确定

// 泛型:在定义函数、接口、类时不确定使用的数据类型,只有在使用函数、接口、类时才确定
(()=>{
    // const getArr = <T>(value:T, num:number):T[]=>{
    //     const arr: T[] =  new Array(num).fill(value)
    //     return arr
    // }
    function getArr<T>(value:T, num:number):T[]{
        const arr: T[] =  new Array(num).fill(value)
        return arr
    }

    console.log(getArr<number>(123,3))
    console.log(getArr<string>('ccc',8))
})()

多个泛型参数的函数

(() => {
  function getMsg<K, V>(value1: K, value2: V): [K, V] {
    return [value1, value2];
  }
  const arr = getMsg<string,number>('abc',21.121)
 
  console.log(arr[0].split(''),arr[1].toFixed(1))
})();

泛型接口

在定义接口时,为属性或方法指定泛型类型,在使用时,才确定具体的泛型类型

(()=>{

    interface IBaseCRUD<T> {
        data: Array<T>
        add:(user: T) => T
        getUserById:(id: number) => T
    }

    class User {
        id?: number
        name: string
        age: number
        constructor(name:string,age:number){
            this.name = name
            this.age = age
        }
    }

    class UserCRUD implements IBaseCRUD<User>{
        data: Array<User> = []

        add(user: User):User{
            user.id = Date.now()+Math.random()
            this.data.push(user)
            return user
        }

        getUserById(id: number): User{
            return this.data.find(e=>e.id===id)
        }
    }

    const ucrud = new UserCRUD()
    ucrud.add(new User('andy',1))
    ucrud.add(new User('bonnie',12))
    ucrud.add(new User('kitty',31))

    console.log(ucrud.data)
    
    const {id} =  ucrud.add(new User('billy',2))

    const u1 = ucrud.getUserById(id)
    console.log(u1)
})()

泛型类

泛型类: 定义一个类,传参、属性与返回值是泛型

(()=>{
    class Generic<T>{
        defaultValue: T
        add:(x:T, y:T) => T
    }

    const g1:Generic<string> = new Generic<string>()
    g1.defaultValue = 'Bonnie'
    g1.add = (x:string, y:string):string => {
        return x+'_'+y
    }
    console.log(g1.add('史','湘云'))
    console.log(g1.add(g1.defaultValue,'湘云'))

    const g2:Generic<number> = new Generic<number>()
    g2.defaultValue = 99
    g2.add = (x:number, y:number):number => {
        return x+y
    }
    console.log(g2.add(1,2))
    console.log(g2.add(g2.defaultValue,3))
})()

泛型约束

如果我们对泛型参数取length属性,会报错,因为泛型不知道它有这个属性

(()=>{
    interface ILen{
        length:number
    }
    function getLen<T extends ILen>(x:T):void{
        console.log(x.length) 
    }
    getLen<string>('abcd')
    // getLen<number>(12)
})()

十三、其他

声明文件

/* 
当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。
声明语句: 如果需要ts对新的语法进行检查, 需要要加载了对应的类型说明代码
  declare var jQuery: (selector: string) => any;
声明文件: 把声明语句放到一个单独的文件(jQuery.d.ts)中, ts会自动解析到项目中所有声明文件
下载声明文件: npm install @types/jquery --save-dev
*/
//手动声明
import jQuery from 'jquery'


// 定义声明文件 (或者放到jQuery.d.ts文件里(自建))
declare var jQuery:(selector: string)=>any

jQuery('选择器')

内置对象

(()=>{
    /* 1. ECMAScript 的内置对象 */
    // Boolean
    // Number
    // String
    // Date
    // RegExp
    // Error
    let b: Boolean = new Boolean(1)
    let n: Number = new Number(true)
    let s: String = new String('abc')
    let d: Date = new Date()
    let r: RegExp = /^1/
    let e: Error = new Error('error message')
    // b = true
    console.log(b)
    // let bb: boolean = new Boolean(2)  // error

    // 2. BOM 和 DOM 的内置对象
    // Window
    // Document
    // HTMLElement
    // DocumentFragment
    // Event
    // NodeList

    const div: HTMLElement = document.getElementById('test')
    const divs: NodeList = document.querySelectorAll('div')
    document.addEventListener('click', (event: MouseEvent) => {
    console.dir(event.target)
    })
    const fragment: DocumentFragment = document.createDocumentFragment()

    console.log(div,divs,fragment)
})()

上一篇:关于java内使用位运算实现加减乘除运算的数据结构问题


下一篇:分别统计每个文档内特定内容的数量