简单回顾typescipt(一)

196 阅读5分钟

概念:

  1. TypeScript的作者是安德斯·海尔斯伯格,C#的首席架构师。2012年10月,微软发布了首个公开版本的TypeScript,2013年6月19日,在经历了一个预览版之后微软正式发布了正式版TypeScript,是由微软开发的开源、跨平台的编程语言。
  2. TypeScript是为大型应用的开发而设计,并且可以编译为JavaScript。
  3. TypeScript 是 JavaScript 的一个超集,TypeScript扩展了JavaScript的语法,任何现有的JavaScript程序都可以运行在TypeScript环境中。也提供了类型系统和对 ES6+ 的支持
  4. TypeScript 是 JavaScript 的强类型版本。然后在编译期去掉类型和特有语法,生成纯粹的 JavaScript 代码。由于最终在浏览器中运行的仍然是 JavaScript,所以 TypeScript 并不依赖于浏览器的支持,也并不会带来兼容性问题。

类型

  • any
// 表示任意类型的值, 如果声明变量不指定类型,则TS解析器会自动判断变量类型为 any(隐私any)
// 随意更改类型
let d  
d = 10
d = 'string'  
  • unknown
// 表示未知类型的值
// 跟any一样
let e: unknown  
e = 10 
e = 'hello'

any跟unknown的区别:

let s: string
// d类型是any, 它可以赋值给任意变量,也就关闭了s的类型判断了,所以要避免
s = d 

// 报错, unknown实际上是一个安全的any
// unknown的变量,不能直接复制给其他变量
// s = e
  • 类型断言
/**
 * 可以用来告诉解析器变量的实际类型
 * 语法: 
 *     变量 as 类型
 *     <类型>变量
 */
s = e as string
s = <string>e
  • void
// 没有值(undefined)
function show(): void {
    return undefined || null 
}
  • never
function show1(): never {
    throw new Error('报错了')
}

对象设置属性

  • 可选属性
// {} 用来指定对象中可以包含哪些属性,
// 在属性名后面加个?,表示属性是可选的
let f: {
    name: string, 
    age?: number,
    readonly id: number
    
    } // 有且只有name,age可选,其他不能

f = {
    name: '1',
    // age: 15 有也行无也行
    id: 1  // 只能读不能更改值
}
  • 自定义属性
// 至少有name属性
let g: {name: string, [protoName: string]: any}
g = {
    name: "1",
    demo: 2
}

函数结构体声明

/**
 * 设置函数结构的声明:
 *          语法: (形参:类型, 形参:类型....) => 返回值
 */
let h: (a: number, b: number) => number

h = (a: number, b: number) => {
    return a + b
}

// 报错
// h = (a: string, b: number) => {
//     return a + b
// }

数组类型声明

/**
 * 数组类型声明:
 *      类型[]
 *      Array<类型>
 */
let i: string[]
let j: number[]
let k: Array<number>

元祖

/**
 * 元组:新增类型,元组就是固定长度的数组
 *   语法: [类型, 类型, 类型...]
 */
// 只允许两个元素
let l: [number, string]
l = [1, 'str']

枚举类型

/**
 * enum 新增类型 枚举
 *      
 */

enum Gender{
    Male,
    Female
}
let m: {name: string, gender: Gender}
m = {
    name: 'lq',
    gender: Gender.Male
}

console.log(m.gender === Gender.Male);


enum Demo{
    one=11,
    two,
    three=21,
    four
}
log:
    Demo.one  11
    Demo.two  12
    Demo.three  21
    Demo.fout  11

类型别名

// 类型的别名
type myType = 1 | 2 | 3 | 4 

let n: myType
let o: myType

n = 3

接口

对象

interface UseObj {
    name: string,
    age?: number,
    readonly id: number
}

let obj:UseObj = {
    name: '林',
    age: 11,  // 可有可无
    id: 10 // 只读不写
}

函数

interface UseFun {
    (name: string, age: number): void
}
let fun:UseFun = (name, age) => {
    console.log()
}

抽象类

(() => {
    // 抽象类无法被new实例化
    abstract class ParentClass{
        name:string
        constructor(name:string) {
            this.name = name
        }    

        // 定义一个抽象方法
        // 抽象方法使用abstract开头,没有方法体
        // 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
        abstract sayHi():void
    }

    class ChildClass extends ParentClass{
        age: number
        constructor(name: string, age: number) {
            super(name)
            this.age = age
        }
        sayHi() {
            console.log('11');
        }
    }
    let p1 = new ChildClass('l1', 2)
//    let p = new ParentClass('llq')
})()

接口

(function() {


    // 定义类型
    type MyInter1 = {
        name: string,
        age: number,
        [prototype: string]: any
    }

    let p1: MyInter1 = {
        name: 'lq',
        age: 1
    }


    /**
     * 
     * 定义接口
     *     接口可以在定义类的时候限制类的结构
     *       接口只定义对象的结构,而不考虑实际值
     *         接口中所有的属性都不能有实际的值
     *          在接口中的所有方法都是抽象方法
     */
    interface MyInter {
        name: string,
        age: number,
        sayHi(): void;
    }



    /**
     * 
     * 定义类时, 可以使类去实现一个接口,
     *      实现接口就是使类满足接口的要求
     * */
    class Myclass implements MyInter {
        name: string
        age: number
        constructor(name: string, age: number) {
            this.name = name
            this.age = age
        }
        sayHi(): void {
            console.log(1);
        }
    }


})()

interface和type的异同

interface侧重于描述数据结构
type(类型别名)侧重于描述类型

type age = number
type dataType = number | string

属性的封装

01

(function() {
    class Person{
        /**
         *  
         *  public 修饰的属性可以在任意位置访问(修改),包括子类, 默认值
         *  
         *  private 私有属性,私有属性只能在类内部访问(修改),不能被子类访问
         *          通过在类中添加方法使得私有属性可以被外部访问
         * 
         *  protected 保护属性,只能在当前类和子类中被访问
         */
        private name: string

        constructor(name: string) {
            this.name = name
        }


        getName() {
            return this.name
        }

        setName(value: string) {
            if(value !== 'moy') {
                this.name = value
            }
        }
    }

    let p = new Person('lq')
    console.log(p.getName);
    p.setName('lq1')
})()

02

(function() {
    class Person{
        private _name: string

        constructor(name: string) {
            this._name = name
        }


        /**
         * 
         * getter方法获取属性
         * setter方法设置上属性
         *     - 它们被称为属性的存取器
         */
        // TS设置中设置getter方法的方式
        get name() {
            return this._name
        }

        set name(value: string) {
            this._name = value
        }
    }

    let p = new Person('lq')
    console.log(p.name);
    p.name = 'lq1'
})()

03

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

    //----------------  等价于 ------------------

    class Person1{
        // 直接把属性定义在构造函数中
        constructor(public name: string) {}
    }

    let p1 = new Person1('lq')
    console.log(p1);
    
}
)()

泛型

/**
 * 
 * 在定义函数或者类时,如果遇到类型不明确就可以使用泛型
 * 
 */

function fn<T>(a: T): T{
    return a
}


// 可以直接调用具有泛型的函数
let result1 = fn(10) // 不指定泛型,TS可以自动对类型进行推断
let result2 = fn<string>('lq') // 指定泛型

// -----------------------------------------

function fn1<T, K>(a: T, b: K): T{
    console.log(b);
    return a
}
let result3 = fn1<string, number>('lq', 12)

// -----------------------------------------

interface Inter{
    length: number
}

// T extends Inter 表示泛型T必须是Inter实现类(子类)
function fn3<T extends Inter>(a: T): number {
    return a.length
}

let result4 = fn3({
    length: 3
})


// -----------------------------------------


class Myclass<T> {
    name: T
    constructor(name: T) {
        this.name = name
    }
}

const mv = new Myclass<string>('lq')