TypeScript学习笔记

初识TypeScript

TypeScript是JavaScript类型的超集,简称TS,包含JavaScript语法支持ES6标准,所以在学习TypeScript之前一定要先学会ES6,TypeScript是由微软开发的自由和开源的编程语言,TypeScript支持类型定义、类、接口、枚举、泛型等特性,所以其设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的JavaScript可以运行在任何浏览器上。

TypeScript的特点:
1.编译JavaScript
TypeScript可以编译出纯净、简洁的JavaScript代码,并且可以运行在任何浏览器上,Node.js环境中和任何支持ECMAScript 3(或更高版本)的JavaScript引擎中。
2.类型系统
类型系统(静态类型化)可以在开发人员编写脚本时检测错误,查找并修复错误是当今开发团队的迫切需求。有了这项功能,开发人员可以编写出可读性高,维护性强的代码。
3.开发大型项目
有时为了改进项目,需要对代码库进行小的增量更改。这些小小的变化可能会产生严重的、意想不到的后果,因此有必要撤销这些变化。使用TypeScript工具来进行重构变的容易、快捷。
4.更好的协作
在开发大型项目时,会有许多开发人员,此时会出现各种各样的问题和bug,类型系统检测是一种在编码期间检测错误的功能,而不是在编译项目时检测错误,这为开发团队创建了一个更高效的编码和调试的过程。

数据类型与推断

TypeScript在声明变量或是函数时需要添加约束也叫类型注解,支持的基本数据类型和引用类型有:
string、number、boolean、null、undefined、symbol、array、object、Function、any,
空值可以使用void来表示,void可以表示变量,也可以表示函数返回值。

let hello:string="hello world"; //必须为字符串类型
let message:any=”我是任意类型”;

接口与联合类型

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

//联合类型 使用|支持多个类型
let muchtype:string|number="hello";
muchtype=1;
muchtype=true//报错

接口可以理解为一种类型,一个规范,一个约束,可以对数组、对象、类进行约束,接口中可定义可选属性、只读属性、任意属性,这样在开发代码时便于调试。

interface Istate{
    name:string;
    age:number;   
}
let user:Istate={name:"张三",age:10}

接口也支持可选属性,代码示例如下:


interface Istate2{
    name:string;
    age?:number;//加上问号表示存疑,可有可无
}
let user2:Istate2;
user2={name:"张三",age:20};
user2={name:"李四"}

接口也支持只读属性,代码示例如下:

interface Istate2{
    readonly name:string; //readonly只读,name不能更改
}
let user2:Istate2;
user2={name:"李四"}
user2.name="王五";//不能更改,否则报错

接口的属性也支持联合类型,代码示例如下:

interface Istate3{
    name:string|number;//可以是联合类型
}
let user3:Istate3={name:"张三"}
user3={name:18}

如果对象属性个数不确定的情况下,可以这样定义,代码示例如下:

interface Istate3{
    name:string|number;//可以是联合类型
    age:number;
    [propName:string]:any; 
    //[propName1:string]:any;//动态添加属性 propName自定义
}
let user3:Istate3={name:"张三",age:10,gender:"男",money:2000000}

接口也可以约束数组,代码示例如下:

interface IArray{
    [index:number]:number;
}
let array:IArray=[1,2,3,1]

数组与元组

数组对象是使用单独的变量名来存储一系列的值。最常见的定义方式有两种,第一种是类型+方括号定义,第二种是数组泛型来定义。

let arr:number []=[1,2,3];
let arr2:string []=["1","2","3"];
let arr3:any []=[1,"2",true];

数组泛型的方式,代码示例如下:

let arrType:Array<number>=[1,2,3];
let arrType2:Array<string>=["1","2","3"];
let arrType3:Array<any>=[1,"2",true];

元组的代码示例:

let arr4:[number,string,boolean]=[1,"大家好",true];
let arr5:[{name:string,age:number}]=[{name:"大家好",age:1}]

函数类型

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

声明一个参数约束和返回值约束的函数,代码示例如下:

function funcType(name:string,age:number):number{
    return age
}
let ageNum:number=funcType("张三",18);

如果函数的参数出现了可选参数可以使用问号来进行约束,代码示例如下:

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

funcType("张三",18,"男");
funcType("张三",18);

如果函数的参数不确定,可以使用扩展运算符的方式来定义动态参数,代码示例如下:

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);

函数的参数也可以设置默认值,这一点和ES6是一样的,区别就是要给参数设置一个类型约束

function funcType(name:string="张三",age:number=18):number{
    return age;
}

也可以声明表达式类型的函数,代码示例如下:

let funcType:(name:string,age:number)=>number=function(name:string=”张三”,age:number=20):number{
    return age
}

也可以使用接口来约束函数,代码示例如下:

interface IFuncType{
    (name:string,age:number):number;
}
let funcType:IFuncType=function(name:string,age:number):number{
    return age;
}

对于联合类型的函数,可以使用重载的方式实现,代码示例如下:

//重载
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);

如果函数没有返回值可以使用void来定义,代码示例如下:

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

类型断言

类型断言可以用来手动指定一个值的类型,将一个联合类型的变量指定为一个更加具体的类型。

//类型断言
function getAssert(name:string|number){
    // return (<string>name).length;//<string>name类型断言,不支持jsx
    return (name as string).length;//使用as实现类型断言
}
getAssert("张三");//2
getAssert(30);//undefined
注意:类型断言不是类型转换,断言成一个联合类型不存在的类型是不允许的。

类型别名

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

//约束数值类型
type strType=string|number|boolean|object;
let str:strType="10";
str=10;
str=true;
str={name:"aa"}
//约束字符串
type gender="男"|"女";
function getGender(s:gender):string{
    return s;
}
getGender("男");

枚举

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

枚举里面的元素默认情况下从0开始为元素的编号,也可以手动的指定成员的编号,代码示例如下:

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

类的修饰符

在TypeScript中类的修饰符有public、private和protected这三个修饰符,接下来看一下这三个修饰符的说明:

public修饰的属性或方法是共有的,可以在任何地方被访问到,默认所有的属性或者方法都public的。
private修饰的属性或方法是私有的,不能在声明它的类外面访问,只能在本类内部访问使用。
protected修饰的属性或者方法是受保护的,它和private类似,唯一的区别是可以在继承的类中访问,比如父类的protected成员成为子类的protected成员,只允许子类成员访问。

class Person{
    public name="张三";//公共,默认为public
    age=18;
    private gender="男";//私有
    protected height="175";//受保护的
    public say(){
        console.log("我叫:"+this.name+",性别:"+this.gender+",身高:"+this.height);
    }
}
let p=new Person();
console.log(p.name,p.age);
p.say();

class Child extends Person{
    callParent(){
        console.log(this.height);
    }
}
let c=new Child();
c.callParent();

接口约束类

在面向对象编程中,接口是一种规范的定义,它定义了行为和动作规范,在开发大型项目时通常采用面向对象的编程思路,那么就要用到接口来约束类,实现高内聚低耦合的代码规范。

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

interface IIronMan{
    eat:Function
}

interface ISpiderMan{
    run:Function
}
interface IMan extends ISuperMan,IIronMan,ISpiderMan{}
class Man implements IMan{
    name:string="超人";
    age:number=30;
    fly(){
        console.log(`${this.name}在飞`)
    }
    eat(){

    }
    run(){

    }
}
let man=new Man();
man.fly();

泛型

泛型是指在定义函数、接口或类的时候,不预先指定具体类型,而在使用的时候在指定类型的一种特性,比如定义一个带有参数的函数,未来在调用这个函数时,传入的值类型不确定,有可能是string,也有可能是number,这时可以使用泛型来解决这样的问题。

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

let strArray: string[] = createArray<string>(3, "张三");
console.log(strArray);

let numArray: number[] = createArray<number>(10, 1);
console.log(numArray);

一个函数也可以有多个泛型参数

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

泛型接口

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

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

泛型接口在类中如何使用

//泛型接口
interface IUser<T>{
    name:string;
    age:number;
    getUserInfo:()=>T
}
//定义一个用户类
class User implements IUser<string>{
    public name:string;
    public age:number;
    constructor(name:string,age:number){
        this.name=name;
        this.age=age;
    }
    getUserInfo(){
        return `姓名${this.name},年龄${this.age}`;
    }
}
let user=new User("张三",30);
console.log(user.getUserInfo());//结果:姓名张三,年龄30

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

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

let ct1=new Counter<number>();
ct1.num=10;
ct1.total(100,ct1.num);

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

泛型约束

泛型约束是指确保泛型类使用的参数是提供特定方法的类型,比如直接对一个泛型参数使用length属性或是用push()方法,会报错,因为这个泛型根本不知道它有这个属性或是这个方法,使用泛型约束可以解决这一的问题。

interface IArrayFunc{
    //可以在setArray函数中使用push方法
    push:Function;
    //可以在setArray函数中使用length属性
    length:number;
}
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");

命名空间

命名空间主要用于组织代码,避免命名冲突,解决重名的问题,在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数、类、接口等放置到命名空间内,TypeScript的命名空间使用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();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值