TypeScript

安装TypeScript

初始TypeScript

TypeScript的设计目标是开发大型应用。它可以编译成纯JavaScript,编译出来的JavaScript可以运行在任何浏览器上(说明兼容性特别好)

TypeScript支持 类型定义、类、接口、枚举、泛型等特性。

TypeScript是 JavaScript类型的超集,简称TS。包含JavaScript语法,支持ES6标准。

安装TypeScript

打开cmd命令提示符窗口,输入命令:

npm install -g typescript

检测是否安装成功,输入命令:

tsc -v

数据类型与推断

数据类型

基本数据类型

string、number、boolean、 null、undefined、symbol

引用类型

array、object、Function、any(表示任意类型,即没有固定类型)

空值

void(表示变量,也可以表示函数返回值。)

创建 ts文件

1、hello.ts代码如下

let hello:string="hello YAP";
hello="hello DJQ";
let message:any="我是任意类型";
message=20;
console.log(hello);
console.log(message);
View Code

编译 ts 文件

方法1

在项目目录的终端下,输入以下命令 ,编译ts文件:

tsc ./1、hello.ts    //编译成功,多出一个 1、hello.js 文件,然后就可以在相关的 html文件中引用该 js文件,再运行该 html文件。
//或者直接在终端输入 node 1、hello.js ,运行 该js文件。

方法2

全局安装 ts-node模块

打开cmd命令窗口,输入命令

npm install -g ts-node

直接访问ts文件进行测试

直接运行ts文件,输入命令

ts-node 1、hello.ts

安装TypeScript运行助手

npm install -D tslib @types/node  

接口与联合类型

联合类型 |

表示取值可为多种类型之一。

可以通过管道 (|),将变量设置为多种类型。赋值时,可以根据设置的类型来赋值。

 

let muchType:string|number="hello";
muchType=20;
View Code

 

接口

可以理解为一种类型,一个规范,一个约束。可以对数组、对象、类进行约束。

接口中可定义 可选属性、只读属性、任意属性。这样在开发代码时便于调试。

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

let user:Istate={name:'YAP',age:25};  //接口的值必须是一个对象。
View Code

支持 可选属性 ?

interface Istate{
    name:string;
    age?:number;  //?表示可选属性。即可有可无。
}

let user:Istate;
user={name:'YAP',age:25};  
user={name:'DJQ'};  
View Code

支持 只读属性 readonly

interface Istate{
    name:string;
    readonly age:number;  //readonly表示只读属性
}

let user:Istate;
user={name:'YAP',age:25};  
//user.age=20;  报错。只能初始化时被赋值。后面不能更改。
View Code

支持 联合类型 |

interface Istate{
    name:string;
    age:number|string;  //|表示联合类型
}

let user:Istate;
user={name:'YAP',age:25};  
user={name:'DJQ',age:'25'};  
View Code

对象属性个数不确定  [propName:string]:any

interface Istate{
    name:string;
    age:number|string; 
    [propName:string]:any; //动态添加属性 propName自定义
}

let user:Istate;
user={name:'YAP',age:25};  
user={name:'DJQ',age:'25',address:'广州',job:"saler"};  
View Code

约束数组  [index:number]:any

interface IArray{
    [index:number]:number|string; //约束数组 index自定义,[]中的number代表数组索引类型
}

let array:IArray=[1,2,3,1,"yap"];
View Code

 

数组与元组

联合类型也可以在数组和元组的定义中使用。

数组

数组对象,是使用单独的变量名,来存储一系列的值。

两种定义方式。

类型+方括号 来定义

let arr:number []=[1,2,3];

let arr2:string []=["1","2","3"];

let arr3:any []=[1,"2",true];
View Code

数组泛型 来定义

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

let arrType2:Array<string>=["1","2","3"];

let arrType3:Array<any>=[1,"2",true];
View Code

元组

表示把数组的格式都定义好了。

let arr4:[number,string,boolean]=[1,"大家好",true];

let arr5:[{name:string,age:number}]=[{name:"YAP",age:25}];

let arr6:[{name:string,age:number},{name:string,age:number}]=[{name:"YAP",age:25},{name:"DJQ",age:25}];
View Code

函数类型

函数类型的约束,支持有函数本身的参数约束和返回值约束。如果想支持联合类型的函数关系,可以使用重载方式。

参数约束和返回值约束

//声明一个 参数约束和返回值约束 的函数。
function funcType(name:string,age:number):number{
    return age;
}

let ageNum:number=funcType("张三",18);
View Code

可选参数 

function funcType(name:string,age:number,gender?:string):number{
    return age;
}

let ageNum:number=funcType("张三",18);
funcType("李四",18,"男");
View Code

参数不确定

可以使用扩展运算符的方式来定义动态参数。
//如果参数不确定,可以使用扩展运算符的方式来定义动态参数。
function dynFuncType(name:string,age:number,...args:any):any{
    console.log(args);//结果:["11","22","33"]
    return args;
}

let dynUser:any=dynFuncType("张三",18,"11","22",33);
View Code

参数默认值

//与es6一样,区别在于要给参数设置一个类型的约束。
function funcType(name:string="张三",age:number=18):number{
    return age;
}
View Code

表达式类型的函数

let 函数名(参数)=>返回类型=function(参数):类型{...}
//表达式类型的函数
//es6的箭头:let 函数名(参数)=>返回类型=function(参数):类型{...}
let funcType2:(name:string,age:number)=>number=function(name:string="张三",age:number=20):number{
    return age;
}
View Code

使用接口来约束函数

let 函数名:接口=function(参数):类型{...}
//定义一个接口
interface IFuncType{
    (name:string,age:number):number;
}
//let 函数名:接口=function(参数):类型{...}
let funcType3:IFuncType=function(name:string,age:number):number{
    return age;
}
View Code

联合类型的函数

可以使用重载的方式实现

//重载
function getValue(value:number):number;
function getValue(value:string):string;
//联合类型的函数
function getValue(value:string|number):string|number{
    return value;
}

let val:string=getValue("张三");
let val2:number=getValue(18);
View Code

函数没有返回值

//void 规定函数没有返回值
function fun():void{
    let age=20;
}
View Code

类型断言

手动指定一个值的类型。将一个联合类型的变量,指定为一个更加具体的类型。

/*类型断言*/
//注意:类型断言不是类型转换,断言一个联合类型不存在的类型是不允许的
function getAsset(name:string|number){
    return (name as string).length;  //使用as,实现类型断言,在jsx(react中的ts版)中使用这种方式。
}

getAsset("张三");
getAsset(30);
View Code

类型别名

用来给一个类型起一个新名字。采用关键字type定义,可以设置字符串和数值类型。

约束数值类型

type strType=string|number|boolean;
let str:strType;
str="10";
str=10;
str=true;
View Code

约束字符串类型

type gender="男"|"女";
function getGender(s:gender):string{
    return s;
}
getGender("男");
//getGender("55"); 会报错
View Code

枚举

用于取值被限定在一定范围内的场景。是对JavaScript标准数据类型的一个补充。

定义数值集合,枚举会员会被赋值为0开始递增的数字,同时也会被枚举值到枚举名进行反向映射。

/*枚举*/
enum Days{
    Sun,
    Mon,
    True,
    Wed,
    Thu,
    Fri,
    Sat
}
console.log(Days.Sun);  //使用枚举名,可以获取到枚举值
console.log(Days[0]);   //使用枚举值0,可以获取到枚举名Sun
console.log(Days.Sat);  //6
console.log(Days[6]);   //Sat
console.log(Days);      //枚举类型会被编译成一个双向映射的对像
View Code

可以手动指定成员的编号

enum Color{
    Red=10,
    Green=9,
    Blue=1000
}
console.log(Color);

enum Color2{
    Red,      //0
    Green=9,  //9
    Blue,     //10
}
console.log(Color2);
View Code

类的修饰符

目的是为了方便阅读代码。

public

共有,全局访问。

private

私有,不能类外访问。

protected

受保护,和private的区别是可以在继承的类中访问。

demo

/*类的修饰符*/
class Person{
    public name="张三";
    private gener="男";
    protected height="175";
    age=18;
    say(){
        console.log("我叫:"+this.name);
        console.log("性别:"+this.gener); //private属性可以类内访问
        console.log("身高:"+this.height); //protected属性可以类内访问
    }
}
let p=new Person();
console.log(p.name,p.age);
p.say();
//p.gener;  会报错,private属性不可以类外访问
//p.height; 会报错,protected属性不可以类外访问

//定义Person类的子类Child
class Child extends Person{
    callParent(){
        console.log(this.height);    //子类内可以访问 父类的protected属性
        //console.log(this.gener);   会报错,子类内不可以访问 父类的private属性
    }
}
let c=new Child();
c.callParent();
View Code

接口约束类

接口是一种规范的定义。定义了行为和动作。用来约束类,实现高内聚低耦合的代码规范。

类继承接口使用关键字 implements,表示该类是实现类

接口继承接口使用关键字 extends,表示该接口是子接口。

速记,同类继承/同接口继承用extends,表示父子关系。

在接口中定义成员方法

fly()

fly:Function

fly:Object

fly:()=>void
View Code

类继承一个接口

interface ISuperMan{
    age:number;
    name:string;
    fly:Function;
}

class Man implements ISuperMan{
    age:number=30;
    name:string="超人";
    fly(){
        console.log(this.name + "在飞");
    };
}

let man =new Man();
man.fly();
View Code

类继承多个接口

interface ISuperMan{
    age:number;
    name:string;
    fly:Function;
}
interface IlronMan{
    eat:Function
}
interface ISpiderMan{
    run:()=>void
}

class Man implements ISuperMan,IlronMan,ISpiderMan{
    age:number=30;
    name:string="超人";
    fly(){
        console.log(this.name + "在飞");
    };
    eat(){};
    run(){};
}

let man =new Man();
man.fly();
View Code

接口继承多个接口

interface ISuperMan{
    age:number;
    name:string;
    fly:Function;
}
interface IlronMan{
    eat:Function
}
interface ISpiderMan{
    run:()=>void
}
//接口继承多个接口
interface IMan extends ISuperMan,IlronMan,ISpiderMan{
}
//类继承接口
class Man2 implements IMan{
    age:number=30;
    name:string="超人";
    fly(){
        console.log(this.name + "在飞");
    };
    eat(){};
    run(){};
}
View Code

泛型

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

比如定义一个带有参数的函数,未来在调用这个函数时,传入的值类型不确定,有可能是string,也有可能是number,这时可以使用泛型来解决这样的问题。

function createArray<T>(length:number,value:T):Array<T>{  //T自定义名称,value:T,T代表未知类型
    let arr:any=[];
    for(let i=0;i<length;i++){
        arr[i]=value;
    }
    return arr;
}

let strArray:string []=createArray<string>(3,"1");
console.log(strArray);  //结果 ['1','1','1']
let numArray:number []=createArray<number>(3,2);//如果不传<number>可以进行类型推断
console.log(numArray);  //结果 [2,2,2,2]
View Code

多个泛型参数的函数

function createMan<T,K>(name:T,age:K):[T,K]{
    return [name,age];
}

let result=createMan<string,number>("张三",30);
console.log(result[0],result[1]);  //结果:张三 30
View Code

泛型接口

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

在函数中的使用

interface ICreate{
    <T>(name:string,age:T):string
}

let func:ICreate=function<T>(name:string,age:T):string{
    return name+","+age;
}

func<number>("李四",20); //结果:李四 20
View Code

在类中的使用

//定义一个接口
interface IUser<T>{
    name:string;
    age:number;
    getUserInfo:()=>T
}
//定义一个类来继承接口
class User implements IUser<string>{
    name: string="李四";
    age: number=33;
    getUserInfo(){
        return `姓名${this.name},年龄${this.age}`;
    }
    //想要传参就得添加下面这个构造器
    constructor(name:string,age:number){
        this.name=name;
        this.age=age;
    }
}

let user2=new User("张三",30);
console.log(user2.getUserInfo()); //结果:姓名张三,年龄30
View Code

泛型类

为类中的属性或方法定义泛型类型。在创建类的实例时,在指定特定的泛型类型。

class Counter<T>{
    public num:T;
    total(price:T,amount:T){
        return Number(price)*Number(amount);//如果需要计算,必须转成Number类型。
    }
}

let ctl=new Counter<number>();
ctl.num=0;
ctl.total(100,ctl.num);

let ct2=new Counter<string>();
ct2.num="100";
ct2.total("200",ct2.num);
View Code

泛型约束

指确保泛型类型使用的参数,是提供特定方法的类型。

比如直接对一个泛型参数使用length属性或是用push()方法,会报错。

因为这个泛型根本不知道它有这个属性或是这个方法,使用泛型约束可以解决这一个问题。

interface IArrayFunc{
    push:Function;  //可以在setArray函数中使用push方法
    length:number;  //可以在setArray函数中使用length属性
}
function setArray<T extends IArrayFunc>(data:T,value:string|number){
    data.push(value);
    console.log(data);  //结果为 [1,2,3,'4']
    console.log(data.length); //结果为  4
}

setArray([1,2,3],"4");
View Code

命名空间

避免命名冲突。将相似功能的函数、类、接口等放置到命名空间内。

使用 namespace关键字创建命名空间。

在外部访问命名空间里面的数据,要在数据前面添加export关键字。

namespace A{
    export let message="大家好";
    export class Person{
        public name:string="张三";
        public say(){
            console.log("大家好,我是"+this.name);
        }
    }
}

console.log(A.message);  //结果:大家好

let person=new A.Person();
person.name;   //结果:张三 
person.say();  //结果:大家好,我是张三 
View Code

 

posted @ 2022-07-20 00:15  Strugglinggirl  阅读(74)  评论(0编辑  收藏  举报