TypeScript简洁学习笔记 By Ksanars (更新中)

698 阅读4分钟

个人总结,如有错误望指正。

一句话简单暴力理解TS
TypeScript就是在你声明的变量的后面加一个“:”,冒号后面写你限定的类型,将动态类型语言js规范为一个静态类型语言ts,使其在编译期间就发现可能存在的错误,减少后续因类型原因导致的错误

TypeScript的安装:

npm install -g typescript
从npm全局安装ts

tsc -v
通过tsc查看当前安装的ts版本

hello函数 by ts 与简单类型声明

const hello = (name : string) => {
  console.log(`hello ${name}`)
}

hello('kasnars')

undefined是所有类型的子类型,所有类型都可以被赋值为undefined

let num : number = undefined

将变量设为any 可以任意改变类型和调用方法 但是频繁使用any会丧失ts本身的意义,并且any类型无法触发ide的方法提示

let anydata : any  = 4
anydata = 'is string'
anydata = true

联合类型:

将变量声明为多种类型,不再为单一类型。用 ' | ' 分隔多种类型

let unitype : number | string  = 123
unitype = 'string'

定义数组类型

对数组内的内容进行限制,例如下例将数组内容限制为number

let arrnum : number[] = [1,2,3]
arrnum.push(4)

Tuple元组:类似于将限定了类型的多个数组组合到一起(参考pytho元组)限定几个就只能写几个,下列限定了两个数据,如果出现了第三个数据则会报错

let userinfo : [string, number] = ['kasnars', 20]
userinfo = ['lyx', 18]

interface接口:

1.对对象形状进行描述
2.对类进行抽象
类似与事先规定好了一种类型,可以在定义类的时候直接调用这个接口来声明类型,而不用再去声明string之类

interface Person{
    name: string;
    age: number;
}

let kasnars : Person = {
    name: 'kasnars',
    age: '20'
}

注意:interface的声明中用分号分隔,不是对象中的逗号
一般情况下interface定义了几个类型,调用这个interface的对象也得有几个类型,除非在某一个类型的后面加上问号,加上问号后在调用这个接口进行定义时,有问号的类型为可选项,例如

interface Person{
    name: string;
    age?: number;
}

let kasnars : Person = {
    name: 'kasnars'
}

对接口里的属性添加readonly属性可以将这个属性变为只读,在初次被赋值后不可再被修改,类似与一个const常量,但是const是用于限制一个变量的,readonly用于限制对象里的一个属性。

interface Person{
    readonly id : number;
    name:string;
}

函数声明:

ts函数声明时需要给函数的参数和返回值设定类型,实例如下:

function add (x: number,y: number):number{
    return x + y
}

let result = add(1,2)

函数的参数和接口一样,可以设置一个可选项,同样在可选的参数后加一个问号
注意:可选参数必须放在传入参数中的最后

function add(x:number,y:number,z?number):number{
    ...
}

将函数赋值给一个变量或常量时,这个常量也会被带上类型,例:

const add = function(x:number,y:number):number{
    return x+y
}
//这里的add已经拥有了被定义的类型,需要将add函数赋值给别人时,也需要遵守类型对应的原则
const add2 :(x:number,y:number) => number = add

注意:ts中冒号之后的都是在定义它的类型,故上面代码中add2冒号后面和等于号前面的一长串都是在规定add2的类型,另外上面的=>并非es6中的箭头函数,而是ts用于声明函数返回值类型的标志

ts中类的声明:

与其他一样,简单的类声明只需要在参数的后面规定类型即可

class People{
    name: string;
    constructor(name: string){
        this.name = name
    }
    run(){
        return : `${this.name} is running`
    }
}

const lyx = new People('lyx')
cnosole.log(lyx.run())

ts中类的修饰:(与java类似)
public 公共属性

class People{
    public name: string;
    constructor(name: string){
        this.name = name
    }
    run(){
        return : `${this.name} is running`
    }
}

private 私有属性,仅本身可以调用,实例和子类皆不可调用

class People{
    private name: string;
    constructor(name: string){
        this.name = name
    }
    run(){
        return : `${this.name} is running`
    }
}

protected 保护属性,本身和自己子类可以调用,其他人不可调用,子类需要用extends和super去继承

class People{
    protected name: string;
    constructor(name: string){
        this.name = name
    }
    run(){
        return : `${this.name} is running`
    }
}

readonly 只读属性,所有人可读但不可更改

class People{
    readonly name: string;
    constructor(name: string){
        this.name = name
    }
    run(){
        return : `${this.name} is running`
    }
}

ts中类与接口结合:

1.接口之间可以互相继承
2.接口可以用来对类进行修饰,类中必须用有接口规定的方法

interface Radio{
    switchRadio():void
}
interface Battery{
    checkBatteryStatus():void
}
interface RadioWithBattery extends Radio{
    checkBatteryStatus():void
}

上例实现了接口的继承,在使用接口对class进行限制时要使用implements关键字

class car implements Radio{
    switchRadio(){}
}

class tellphone implements RadioWithBattery{
    switchRadio(){}
    checkBatteryStatus(){}
}

enum枚举:

enum direction{
    Up = 'up',
    Down = 'down',
    Left = 'left',
    Right = 'right'
}

console.log(direction.Up)
//up

//在enum前面加const可使其变为常量枚举,可以提升性能 但并不是所有枚举都适合被声明为常量

泛型:

在定义类型的时候不预先规定其类型,而是在其调用时决定他的类型
简单泛型案例(利用和T对类型进行占位)

function echo  <T> (any: T):T{
    return any
}

const result = echo('123')
//此时result为string类型

const num = echo(123)
//此时num为number类型

将多个类型声明为泛型

function swap<T> (tuple:[T,U]):[U,T]{
    return  [tuple[1],tuple[0]]
}

将接口和泛型结合,通过接口来强制使泛型内拥有某种方法,例

function uselength <T> (arg:T):T{
    console.log(arg.length)
    return arg.length
}
//此时代码会报错,因为uselength是一个泛型,不确定传入的数据到底是什么类型,不确定是否能够使用length属性

此时我们需要用接口去定义一个length属性,然后在定义泛型时使用这个接口,使这个泛型必须拥有此接口规定的属性

interface Ilength{
    length: number
}

function uselength <T extends Ilength> (arg:T):T{
    console.log(arg.length)
    return arg.length
}
//此时代码不会报错

泛型与类结合,实例化时指定所需类型

class queue <T>{
    private data = []
    push(arg:T){
        ...
    }
}

const num = new queue<number>()
//此时num为number属性 可以调用number的方法

接口与泛型结合,在调用接口时规定所需要的类型

interface keypair<T,U>{
    key:T;
    value:U;
}

const key1:keypair<string,number> = {key:'kasnars',value:'20'}

类型别名:利用关键字type给复杂的类型取一个别名简化代码

type numplus = (x: number, y: number) => number

function add(x: number, y:number) : number{
    return x + y
}

const add2: numplus = add 

类型断言 type assertion

在给一个参数声明为联合类型时,编译器无法确定传进来的参数是其中哪一种,所以默认只能使用两种类型的公共方法,而类型断言则直接给他指定为其中的一种,从而让其使用对应类型的方法,例:

function getlength(x: string | number) : number{
    //此时函数x内只能使用string和number都有的公共方法,无法调用属性特有的方法
}

使用类型断言去指定一个类型,向编译器证明,你比他更懂这段代码
进行类型断言有两种方法
1.使用as关键字

const str = x as string
//此时将x指定为了string类型,从而可以去使用string类型的方法

2.使用(<type>arg)格式

(<string>x).length
//此时被括号包括的x被断言为了string类型,可以使用string下的所有方法

注意:类型断言不是类型转换,只能断言为联合类型中有的类型,断言为其他类型会报错,例如上面getlength函数中把x断言为布尔值是不可行的

声明文件:

引用外部库时对外部库进行类型定义,例

declare var jQuery:(selector : string) => any

一般将这种声明文件放到外部一个xxxx.d.ts 以.d.ts结尾的文件中,编译器会自动去解析.d.ts后缀里的声明
一般在使用其他库和ts结合时只需下载官方对应的声明文件即可