typescript

759 阅读9分钟

简介

typescript是javascript的一个超集,主要提供了系统类型和对es6的支持,它是由Microsoft开发,代码开源在github

  • 出现的原因:解决js弱语言的特性
  • typescript是编辑性语言,将ts通过编辑变成js代码
  • js是解释性语言
  • 编译后的ts可以运行在任何服务器、浏览器

为何选择ts

  • 增加了代码的可读性和可维护性
  • 非常包容(例如:编译过程中出现了错误,还是可以继续编译成js,并且编译后的js可以正常的运行)
  • 拥有活跃的社区

安装使用ts

  • 全局安装 npm install -g typescript
  • 编译文件 tsc greeter.ts
  • 约定文件以.ts结尾,编写react时,以.tsc为后缀
  • 主流的IDE中都支持TS,包括代码补全、接口提示、跳转定义、重构

2.数据类型--任意值--推论

ts原始数据类型

  • string number boolean null undefined enum symbol
  • 空值一般用void表示
  • void可以表示变量,也可表示函数无返回值

ts中的任意值

  • 任意值(any)用来表示赋予任意类型
  • 声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值
  • 变量如果在声明的时候,未制定其类型,那么它会被识别为任意值类型
var num: any = 1;
num = true;
num = "3";

var num2;//没有赋值操作,就会被认为任意值类型,等价于var num2:any;
num2 = 1;
num2 = true;

ts中的类型推论

  • typescript会按照类型推论的规则推断出一个类型
var b = 1;  //给变量赋值初始值的时候,如果没有指定类型,根据初始值倒推类型
//所以下面赋值“2”是错的,只能赋值为number类型
b = "2";
  • 如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成any类型而完全不被类型检查
var b;//没有给b赋初始值,就是any。  相当于var b:any;
b = 2;
b = true;

ts联合类型

  • 联合类型表示取值可以为多种类型中的一种
var muchtype:string|number = 3
muchtype = "ee"
  • 如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成any类型而完全不被类型检查

  • 只能访问此联合类型内的所有类型里的共有的属性或者方法

var muchtype:string|number = "string"
muchtype = 10;
//number类型没有length属性,所以下面的代码会报错
console.log(muchtype.length)
//string和number都有toString方法,所以不会报错
console.log(muchtype.toString())

3.联合类型--接口

ts中对象类型--接口

  • 可描述类的一部分抽象行为,也可描述对象的结构形状

  • 接口一般字母大写,有的编程语言上面建议接口的名称加上i前缀

  • 赋值的时候,变量的形状必须要跟接口的形状保持一致

  • 接口中可定义可选属性、只读属性、任意属性

//定义接口
interface Istate {
   name : string
}

var obj1: Istate;
//obj1 = {}   //接口中的name属性必须要写的
obj1 = {name : "张三" 0}


//可选属性
interface Istate2 {
   name : string,
   age? : number   //存疑,可有可无
}

var obj2 : Istate2;
obj2 = { name : "张三" , age : 20 }
obj2 = { name : "李四"}


//当属性个数不确定的时候  any必须是任意类型
interface Istate3 {
   name : string,
   age? : number,
   [propname : string] : any
}
var obj3:Istate3 = {name : "张三" , age : 10 , sex : "男"}

//只读属性
interface Istate4 {
    name : string,
    readonly age : number
}
var obj4:Istate4 = { name : "张三" , age : 10};
//obj4.age = 20;    //age一旦赋予初始值之后。就不能再对其进行更改了

4.数组类型

  • 可采用[类型 + 方括号]表示法
//数组表示法
//类型+方括号
var arr:number [] = [1,2,3]
var arr2:string [] = ["1","2","3"]
var arr3:any [] = [1,"2" , true]
  • 可采用数组泛性Array表示法
var arrType: Array<number> = [1 , 2, 3]
var arrType2: Array<string> = ["1" , "2" , "3"]
var arrType3: Array<any> = [1 , "2" , true]
  • 可采用接口表示法
interface Istate {
    usename : string,
    age : number
}
var arrType4:IArr = [1 , 2, 4]
interface Istate {
    username : string,
    age : number
}
interface IArr {
    [inde: number] : Istate
}

var arrType4:IArr = [{username : "张三" , age : 22}]
var arrType5: Array<Istate> =  [{username : "张三" , age : 22}]
var arrType6:Istate[] =  [{username : "张三" , age : 22}]

5.函数类型

函数约束 有函数本身的参数约束,返回值约束 还有函数本身赋值的变量的约束

//声名式类型的函数
function funcType(name : string , age : number):number {
    return age;
}
var ageNum : number = funcType("张三" , 18)


//函数参数不确定
function funcType2(name : string , age : number , sex? :string):number {
    return age;
}
var ageNum2:number = funcType2("张三" , 18 , "男")


//函数参数默认值
function funcType3(name : string , age : number=18):number {
    return age;
}


//表达式类型的函数
var funcType4 = function(name : string , age:number):number {
    return age;
}
//函数变量的约束规范
//第一种方法
var funcType5:(name : string , age:number)=> number = function(name : string , age:number):number {
    return age;
}
//第二种方法
interface funcType6 {
    (name : string , age : number) : number
}
var funcType6:funcType6 = function(name : string , age:number):number {
    return age;
}

可采用重载的方式来支持联合类型的函数关系

//对于联合类型的函数,可以采用重载的方式
//输入是number,输出也是number
//输入是string,输出也是string
function getValue(value : number):number
function getValue(value : string) : string
function getValue(value : string|number):string|number {
    return value
}
let a:number|string = getValue(1);
let b:number = getValue(1);
let c:string = getValue("1");

6.类型断言

  • 类型断言可以用来手动指定一个值的类型,语法:<类型>值或者值as类型
  • 在tsx语法(react的jsx语法的ts版)必须采用后面一种
  • 类型断言不是类型转换,断言成一个联合类型中不存在的类型是不允许的

如果要使用某一种类型的方法或者属性,解决下面的问题

// let num:number|string = "18";
// num = 20;
// console.log(num.length)

解决方法

//类型断言,只能断言联合类型中存在的类型
function getAssert(name:string|number) {
    // return (<string>name).length
    return (name as string).length
}

7.类型别名

  • 类型别名可以用来给一个类型起一个新名字
  • 采用关键字type 例如type Name = string | number
  • 例子中name就表示可设置字符串和数值类型
  • 也可采用type来约束取值只能是某些字符串中的一个,:如
  • type EventNames = "click"|"scroll"|"mousemove"
//类型别名
// var str:string|number = "10";

type strType = string|number|boolean;
var str:strType = "10";
str = 10;
str = false;

//可以对于接口也采用类型别名
interface muchType1 {
    name : string
}
interface muchType2 {
    age : number
}
type muchType = muchType1 | muchType2
var obj : muchType = { name : "张三"}
var obj2: muchType = {age : 10}
var ocj3: muchType = { name : "张三" , age : 10}
//限制字符串的选择
type sex = "男" | "女"
function getSex(s:sex):string {
    return s;
}

getSex("男")

8.枚举

  • 枚举(Enum)类型用于取值被限定在一定范围内的场景
  • 采用关键字enum定义,例如:enum Days{Sun , Mon , Tue , Wed , Thu , Fri,Sat}
  • 枚举成员会被赋值为从0开始递增的数字,同时也会被枚举值到枚举名进行反向映射
//使用枚举可以定义一些有名字的数字常量
enum Days {
    Sun,
    Mon,
    Tue,
    Wed,
    Thu,
    Fri,
    Sat
}

console.log(Days.Sun) // 0
console.log(Days.Sat) // 6

console.log(Days)  //枚举类型会被编译成一个双向映射的对象
console.log(Days[0] === "Sun") //true

如果给予默认值,从给予的默认值开始累加

//使用枚举可以定义一些有名字的数字常量
enum Days {
    Sun=3,
    Mon,
    Tue,
    Wed,
    Thu,
    Fri,
    Sat
}

console.log(Days.Sun) // 3
console.log(Days.Sat) // 9

9.修饰类型

public private protected

  • public修饰的属性或者方法是共有的,可以在任何地方被访问到,默认所有的属性或者方法都是public上午
  • private修饰的属性或者方法是私有的,不能在声明它的类外面访问
  • protected修饰的属性或者方法是受保护的,它和private类似
//创建person类
class Person {
    name="张三"
    age=18
    say() {
        console.log("我的名字是"+this.name+",我的年龄是" + this.age)
    }
}

//创建person实例
var p = new Person();
p.say()
console.log(p.name);    //当一个类成员变量没有修饰的时候,外界是可以进行访问的,默认就是public进行修饰

假设name不希望外界访问

private属性只能在类的内部进行访问,在外面无法访问被private修饰的属性或者方法

//创建person类
class Person {
    private name="张三"
    age=18
    say() {
        console.log("我的名字是"+this.name+",我的年龄是" + this.age)
    }
}

//创建person实例
var p = new Person();
p.say()
//console.log(p.name); 这句话会报错

//private属性只能在类的内部进行访问,在外面无法访问被private修饰的属性或者方法

子类继承了父类,子类就可以访问到父类公开的属性或者方法了

//创建person类
class Person {
    private name="张三"
    age=18
    say() {
        console.log("我的名字是"+this.name+",我的年龄是" + this.age)
    }
}

//创建child子类
//一旦父类将属性定义成私有之后,子类就不可以进行访问了
class Child extends Person {
    callParent(){
        super.say()
    }
}

var c = new Child();
c.callParent();
console.log(c.age); //子类继承了父类,子类就可以访问到父类公开的属性或者方法了

子类继承了父类,但是没有办法直接获取到父类私有的属性或者受保护的属性

//创建person类
class Person {
    private name="张三"
    protected age=18
    say() {
        console.log("我的名字是"+this.name+",我的年龄是" + this.age)
    }
}

//创建child子类
//父类的属性定义成受保护的之后,可以在子类里面进行访问
class Child extends Person {
    callParent(){
        console.log(super.age)
        super.say()
    }
}

var c = new Child();
c.callParent();
console.log(c.age); //子类继承了父类,但是没有办法直接获取到父类私有的属性或者受保护的属性

类的静态方法里面,是不允许使用this

//创建person类
class Person {
    private name="张三"
    protected age=18
    say() {
        console.log("我的名字是"+this.name+",我的年龄是" + this.age)
    }
}

//创建child子类
class Child extends Person {
    callParent(){
        super.say()
    }
    static test() {
        // console.log("this")  //会报错
    }
}

var c = new Child();
console.log(Child.test()); //类的静态方法里面,是不允许使用this

10.泛型

泛型是指在定义函数、接口或者类的时候,不预先指定具体类型,而在使用的时候再指定类型的一种特性

好处:使得代码更具有健壮性、维护性更高

解决问题:没有确切定义返回值类型,运行的数组每一项可以是任意类型

//没有确切定义返回值类型,运行的数组每一项可以是任意类型
function createArray(length: number , value : any):Array<any> {
    let arr = [];
    for(var i = 0;i<length ; i++) {
        arr[i] = value
    }
    return arr;
}
createArray(3 , 1)

利用泛型将上述代码进行改造,

泛用来帮助我们限定约束规范

function createArray<T>(length : number , value : T):Array<T> {
    let arr = [];
    for(var i = 0;i<length ; i++) {
        arr[i] = value
    }
    return arr;
}

//1.传类型
var strArr: string[] = createArray<string>(3 , "1")

//2.不传的时候根据数据类型进行反推
var numArr:number[] = createArray(3 , 1)

接口当中采用泛型

interface ICreate {
    <T>(name : string , value : T) : Array<T>
}
let func:ICreate;
func = function<T>(name : string , value :T):Array<T> {
    return []
}

var strArr:string [] = func("1" , "2")

11.应用