TypeScript knowledge

Introduction 1.1 Typescript

1.TypeScript is developed by Microsoft open-source programming language, such as the back-end java, C # object-oriented language such js allows development of large enterprise projects.

2.TypeScript Javascript is super, follow the latest ES6, Es5 specification (equivalent to contain the syntax es6, es5's). TypeScript extends the JavaScript syntax.

3. The latest Vue, React can also be integrated TypeScript.

1.2 Typescript install the compiler

Nodejs installation environment, installation typescript with global npm
npm install -g typescript
Typescript file name suffix .ts, and finally compiled into js file

Typescript manually compile => tsc + filename

// 将index.ts编译成index.js
tsc index.ts

1.3 Typescript development tools Vscode automatically compile .ts file

1.3.1 tsc --init generate a configuration file tsconfig.json

image description

1.3.2 menu bar task - to run the task (an error is encountered use the shortcut ctrl + shift + b), click tsc: monitoring -tsconfig.json can then automatically generate the code
of

image description

Two, Typescript data type

typescript in order to make the code written in more standardized, more conducive to the maintenance and a greater parity

2.1 basis of type

In the typescript mainly provides us with the following data types:

Boolean (boolean) 
numeric type (number) 
string type (string) 
array type (Array) 
tuple type (tuple) 
enumerated type (enum) 
of any type (the any) 
null and undefined 
void type 
never type

相比于js,typescript中多了枚举类型、任意类型、void类型和never类型

2.2 变量定义

写ts代码变量必须指定类型,指定类型后赋值必须为指定的类型,否则报错

var flag:boolean = true
flag = 123 // 错误,类型不一致

2.3 数据类型

布尔类型(boolean)

var flag:boolean = true

flag = false // 正确

// flag=123; // 错误

数字类型(number)

var num:number = 123;

num = 456; // 正确 

// num='str'; //错误

字符串类型(string)

var str:string = 'this is ts';

str='haha';  //正确

// str=true; //错误

数组类型(array) ts中定义数组有两种方式

// 第一种
var arr:number[] = [1, 2, 3] // 第二种 var arr2:Array<number> = [1, 2, 3]

元组类型(tuple)元素的类型不必相同,写法和数组一样

let arr:[number,string] = [123,'this is ts']

枚举类型(enum)

用法:

enum 枚举名{ 
    标识符[=整型常数], 
    标识符[=整型常数], 
    ... 
    标识符[=整型常数], 
}
enum Flag {success = 1,error = 2};

let s:Flag = Flag.success // 使用枚举类型中的值
console.log('正确状态',s) let f:Flag = Flag.error console.log('错误状态',f)

任意类型(any)

为那些在编程阶段还不清楚类型的变量指定一个类型

var number:any = 123
number = 'str'
number = true

2.9 null 和 undefined

undefined:

{
    // 在js中,变量已声明但未初始化为undefined
    var undefinedTest:number
    // console.log(undefinedTest) // 错误写法,typescript报错,赋值了才正确

    // 在typescript中,已声明未初始化的值要直接访问的话类型需要定义为undefined
    var undefinedTest2:undefined console.log(undefinedTest2) // 正确写法,输出undefined } { // 可能是number类型 可能是undefined var undefinedTest3:number | undefined; console.log(num); }

null:

// null是一个空指针对象,undefined是未初始化的变量。因此,可以把undefined看作是空的变量,而null看作是空的对象
var nullTest:null
nullTest = null
// nullTest = {} // 错误,定义了类型是null,值必须为null

void类型

typescript中的void表示没有任何类型,一般用于定义方法的时候方法没有返回值。

// 表示方法没有返回任何类型
function run(): void { console.log('run') } run()

never类型

表示的是那些永不存在的值的类型,例如异常
var a:never

// a = 123 //错误写法
a = (() => {
    throw new Error('错误'); })()

三、Typescript函数

内容概述: 函数的定义、可选参数、默认参数、剩余参数、函数重载、箭头函数。

3.1.1 函数的定义

  • es5定义函数有函数声明法和匿名函数法
// 法一:函数声明法

function run():string { return 'run' } /** // 错误写法 function run():string { return 123 } */ // 法二:匿名函数 var run2 = function ():string { return 'run2' } console.log('函数定义一', run()) console.log('函数定义二', run2())

3.1.2 ts中定义方法传参

  • 函数传参要指定数据类型
function paramFuc(name:string, age:number):string{ return `${name} --- ${age}` } console.log('函数传参', paramFuc('dz', 20))

3.1.3 函数没有返回值的方法用void

function voidFnc():void{ console.log('没有返回值的方法用void') } voidFnc();

3.2 可选参数

  • es5里面方法的实参和行参可以不一样,但是ts中必须一样,如果不一样就需要在可选参数后加?,这就是可选参数。
function electParam(name:string, age?:number):string { // 这里的age可传可不传,age就是可选参数 if(age){ return `${name} --- ${age}` }else{ return `${name} --- 年龄保密` } } console.log('可选参数', electParam('dz')) // 注意: 可选参数必须配置到参数的最后面 // 错误写法:可选参数不在最后面 // function electParam2(name?: string, age: number): string { // ... // }

3.3 默认参数

  • es5里面没法设置默认参数,es6和ts中都可以设置默认参数
// age为默认参数
function defaultParam(name:string, age:number = 20):String { return `${name} --- ${age}` } console.log('默认参数', defaultParam('dz'))

3.4 剩余参数

  • 当有很多参数时候或参数个数不确定,可以用三点运算符
// sum参数传过来的是一个数组
function sum(...result: number[]): number { var sum = 0; for (var i = 0; i < result.length; i++) { sum += result[i]; } return sum; } console.log('剩余参数', sum(1, 2, 3, 4, 5, 6)); // a=1 b=2 其他参数为剩余参数 function sum2(a: number, b: number, ...result: number[]): number { var sum = a * b; for (var i = 0; i < result.length; i++) { sum += result[i]; } return sum; } console.log('剩余参数2', sum2(1, 2, 3, 4, 5, 6));

3.5 ts函数重载

同样的函数,传入不同的参数,实现不同的功能
  • java中方法的重载:重载指的是两个或者两个以上同名函数,但它们的参数不一样,这时会出现函数重载的情况。
  • typescript中的重载:通过为同一个函数提供多个函数类型定义来实现多种功能的目的。
  • ts为了兼容es5 以及 es6 重载的写法和java中有区别。
//  es5中同名函数,后面会覆盖前面的函数,ts中则不会 => 函数重载
function getInfo(name:string):string function getInfo(name:string, age:number):string function getInfo(name:any, age?:any):any { if(age) { return '姓名:' + name + '年龄:' + age }else{ return '姓名:' + name } } console.log(getInfo('dz')) console.log(getInfo('dz', 20)) // console.log(getInfo(20)) // 错误

3.6 箭头函数

箭头函数和es6中一样

setTimeout(() => {
    console.log('箭头函数')
}, 1000);

四、Typescript中的类

4.1 es5中的类

内容概述:类的创建、静态方法、继承(对象冒充继承,原型链继承,对象冒充 + 原型链组合继承)

es5中的面向对象、构造函数、原型与原型链本质可以看这个文档http://caibaojian.com/javascr... , 个人觉得写得很清晰。

4.1.1 类的创建

es5类在构造函数和原型链里都可以添加属性和方法,原型链上的属性会被多个实例所共享,而构造函数则不会。


function Person() {
    this.name = 'Ming' this.run = function() { console.log(this.name + '在运动') } } Person.prototype.sex = '男' // 原型链上的属性会被多个实例所共享 Person.prototype.work = function() { console.log(this.name + '在工作') } var p = new Person() p.run() p.work() console.log(p.name) 

4.1.2 静态方法

调用静态方法不需要实例化

Person.getInfo=function(){
    console.log('我是静态方法'); } Person.getInfo(); 

4.1.3 实现继承

对象冒充(或者叫构造函数继承)继承:可以继承构造函数里面的属性和方法,但是没法继承原型链上面的属性和方法

原型继承:可以继承构造函数里面的属性和方法,也可以继承原型链上面的属性和方法,但是实例化子类的时候没法给父类传参

下面是通过对象冒充 + 原型链组合继承,解决了上面两种继承方式存在的问题


function Worker(name,age){
    this.name=name; /*属性*/ this.age=age; this.run=function(){ /*实例方法*/ alert(this.name+'在运动'); } } Worker.prototype.sex="男"; Worker.prototype.work=function(){ alert(this.name+'在工作'); } function Web(name,age){ Worker.call(this,name,age); // 对象冒充继承,可以继承构造函数里面的属性和方法,实例化子类可以给父类传参 } // Web.prototype = new Worker(); // 原型链继承方法一:继承Worker构造函数和原型上所有的方法和属性 Web.prototype = Worker.prototype; //原型链继承方法二:优化了方法一重复继承构造函数属性和方法的问题(本质可以看看http://caibaojian.com/javascript-object-5.html) var w = new Web('赵四',20); w.run(); w.work(); 

从上面可以看出,对象冒充继承是在子类Web构造函数里面通过call方法继承父类Worker的构造函数的属性和方法;原型链继承通过子类Web的原型对象等于父类Worker的原型对象来实现继承;最后这两种继承的组合方式实现了完美继承。

4.2 typescript中的类

内容概述: ts中类的定义、继承、类修饰符、静态属性和静态方法、多态、抽象类和抽象方法

4.2.1 ts中类的定义

ts中类的定义和es6类的定义一样


class PersonDefine {
    name: string // 属性,前面省略了public关键词
    constructor(name:string) { //构造函数 this.name = name } run():string { // 原型 return `${this.name}在运动` } } var define = new PersonDefine('类的定义') alert(define.run()) 

4.2.2 继承

ts中继承比es5简单很多,用extends super实现继承

class WebExtend extends PersonDefine { constructor(name:string) { super(name) // super继承父类的构造函数,并向父类构造函数传参 } work():string { return `${this.name}在工作` } } var extend = new WebExtend('继承') alert(extend.run()) alert(extend.work()) 

4.2.3 ts类里面的修饰符

修饰符:typescript里面定义属性的时候给我们提供了三种修饰符

  • public: 公有修饰符,在当前类里面、子类、类外面都可以访问
  • protected:保护类型,在当前类里面、子类里面可以访问,在类外部没法访问
  • private :私有修饰符,在当前类里面可以访问,子类、类外部都没法访问

注意:属性如果不加修饰符,默认就是公有修饰符


// 以private为例
class PersonPrivate{
    private name:string;  /*被private修饰的属性 => 私有属性*/ constructor(name:string){ this.name=name; } run():string{ return `${this.name}在运动` // 私有属性只能在当前类里面可以访问 } } class Web extends PersonPrivate{ constructor(name:string){ super(name) } work(){ // return `${this.name}在工作` // 报错,子类不能访问父类的私有属性 } } var privateName = new PersonPrivate('private') alert(privateName.run()) // console.log(privateName.name) // 报错,外部不能访问类的私有属性 

4.2.4 静态属性和静态方法

为什么要用静态属性和静态方法?jq里面的$.ajax就是用的静态方法

function $(element) {
    return new Base(element) } function Base(element) { this.element = document.getElementById(element) this.css = function(arr, value) { this.element.style[arr] = value } } $('box').css('color','red') $.ajax = function() {} // 想要在$上使用方法怎么办,用静态方法 
ts中实现静态属性和静态方法用static

class PersonStatic{
    /*公有属性*/
    public name:string;
    constructor(name:string) { this.name=name; } /*实例方法(需要被实例化,所以为实例方法)*/ run(){ return `${this.name}在运动` } /*静态属性*/ static sex = '男' /*静态方法,里面没法直接调用类里面的属性*/ static info(){ // return 'info方法' + this.name // 静态方法不能调用本类的方法和属性,可以调用静态属性 return 'info方法' + PersonStatic.sex } } console.log('静态方法' + PersonStatic.info()) console.log('静态属性' + PersonStatic.sex) 

4.2.5 多态

父类定义一个方法不去实现,让继承它的子类去实现,每一个子类的该方法有不同的表现
  • 多态属于继承

比如定义一个父类Animal,里面的eat方法不去实现,让子类Dog和Cat分别实现自己的eat方法


class Animal {
    name:string;
    constructor(name:string) {
        this.name=name; } eat(){ // eat方法继承它的子类去实现 } } class Dog extends Animal{ constructor(name:string){ super(name) } eat(){ return this.name+'吃粮食' } } class Cat extends Animal{ constructor(name:string){ super(name) } eat(){ return this.name+'吃老鼠' } } 

4.2.6 抽象类和抽象方法

定义:用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类(抽象类的子类)中实现
  • 抽象类:它是提供其他类继承的基类,不能直接被实例化,子类继承可以被实例化
  • abstract修饰的方法(抽象方法)只能放在抽象类里面
  • 抽象类和抽象方法用来定义标准(比如定义标准为:抽象类Animal有抽象方法eat,要求它的子类必须包含eat方法)

abstract class AnimalAbst{
    public name:string;
    constructor(name:string){
        this.name=name; } abstract eat():any; //抽象方法不包含具体实现并且必须在派生类中实现 run(){ console.log('其他方法可以不实现') } } // var a = new Animal() /*错误的写法,抽象类不能被实例化*/ class DogAbst extends Animal{ //抽象类的子类必须实现抽象类里面的抽象方法 constructor(name:any){ super(name) } eat(){ return this.name + '吃粮食' } } var d = new DogAbst('小花花'); console.log('抽象类和抽象方法',d.eat()); 

五、TypesSript接口

接口定义:接口是对传入参数进行约束;或者对类里面的属性和方法进行声明和约束,实现这个接口的类必须实现该接口里面属性和方法;typescript中的接口用interface关键字定义。

接口作用:接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。typescrip中的接口类似于java,同时还增加了更灵活的接口类型,包括属性、函数、可索引和类等。

内容概述:接口分类:(属性接口、函数类型接口、可索引接口、类类型接口),接口的继承

5.1 接口分类

5.1.1 属性接口

对传入对象的约束(也就是对json的约束)

在了解接口之前,我们来看看函数传入obj参数


function printLabel(labelInfo: {label:string}){
    return labelInfo } // printLabel({name:'obj'}); //错误的写法 console.log(printLabel({label: 'obj'})) 

和上面类似,由此引入属性接口 => 对方法传入参数进行约束

下面为属性接口的例子,方法printFullName对传入参数FullName(为对象)进行约束


interface FullName{
    firstName: string; // 注意;结束
    secondName: string;
    age?: number // 接口的可选属性用?
}

function printFullName(name:FullName) { // 传入对象必须包含firstName和secondName,可传可不传age return name } var obj = { firstName:'小', secondName:'明', age: 20 } console.log(printFullName(obj)) 

属性接口应用:原生js封装ajax


interface Config{
    type: string;
    url: string;
    data?: string;
    dataType: string;
}
function ajax(config: Config) { var xhr = new XMLHttpRequest xhr.open(config.type, config.url, true) xhr.send(config.data) xhr.onreadystatechange = function() { if(xhr.readyState == 4 && xhr.status == 200) { if(config.dataType == 'json'){ console.log(JSON.parse(xhr.responseText)) }else{ console.log(xhr.responseText) } } } } ajax({ type: 'get', data: 'name=xiaoming', url: 'http://a.itying.com/api/productlist', dataType: 'json' }) 

5.1.2 函数类型接口

对方法传入的参数以及返回值进行约束

interface encrypt{
    (key: string, value: string): string; // 传入的参数和返回值的类型
}

var md5:encrypt = function(key:string, value:string):string{ // encrypt对加密方法md5进行约束,同时md5方法的参数和返回值类型和encrypt要保持一致 return key + value } console.log(md5('name', '小明')) 

5.1.3 可索引接口

对索引和传入参数的约束(一般用于对数组、对象的约束)

ts中定义数组:


var arr1:number[] = [1,2]
var arr2:Array<string> = ['1', '2'] 

现在用接口来实现:


// 对数组的的约束
interface UserArr{
    // 索引为number,参数为string
    [index:number]: string
}
var userarr:UserArr = ['a', 'b'] console.log(userarr) 

// 对象的约束
interface UserObj{
    // 索引为string,参数为string
    [index:string]: string
}
var userobj:UserObj = { name: '小明', sex: '男' } console.log(userobj) 

5.1.4 类类型接口

对类的约束,和抽象类抽象有点相似

interface Animal{
    // 对类里面的属性和方法进行约束
    name:string;
    eat(str:string):void;
}
// 类实现接口要用implements关键字,必须实现接口里面声明的方法和属性
class Cat implements Animal{ name:string; constructor(name:string){ this.name = name } eat(food:string){ console.log(this.name + '吃' + food) } } var cat = new Cat('小花') cat.eat('老鼠') 

5.2 接口的继承

和类的继承一样,用extends实现接口继承

下面同时实现类的继承和接口的继承


interface Animal {
    eat(): void;
}
// 继承Animal接口,则实现Person接口的类必须也实现Animal接口里面的方法
interface Person extends Animal {
    work(): void;
}

class Programmer { public name: string; constructor(name: string) { this.name = name; } coding(code: string) { console.log(this.name + code) } } // 继承类并且实现接口 class Web extends Programmer implements Person { constructor(name: string) { super(name) } eat() { console.log(this.name + '吃') } work() { console.log(this.name + '工作'); } } var w = new Web('小李'); w.eat(); w.coding('写ts代码'); 

六、TypesSript泛型

泛型定义:泛型定义:泛型就是解决类、接口、方法的复用性,以及对不特定数据类型的支持(类型校验)。ts中用T表示泛型。

泛型公式: <T>表示泛型,调用的时候指定T的数据类型

软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。

在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。

内容概述:内容概述:函数的泛型、类的泛型、泛型接口

6.1 函数的泛型

传入的参数类型和返回的参数类型可以指定

我们来看看函数用ts数据类型,想要同时返回string类型和number类型


function getData1(value:string):string{ return value; } function getData2(value:number):number{ return value; } 

这样要写不同的函数,不能按照需求返回不同类型数据,造成代码冗余 => 由此引入泛型

<T>表示泛型,调用的时候指定T的数据类型

function dataT<T>(value:T):T{ // 传入参数为T 返回值为T return value } dataT<number>(1) // 调用指定泛型为number类型,则传入参数也必须为number类型 dataT<string>('string') function dataAny<T>(value:T):any{ return '传入参数为T,任意类型返回值'; } dataAny<number>(123); // 参数必须是number dataAny<string>('这是一个泛型'); 

6.2 类的泛型

也是用<T>来实现类的泛型,new的时候指定T的数据类型

有个最小堆算法,需要同时支持返回数字和字符串两种类型

使用泛型之前:只能在类的类部指定数据类型,实现需求还要写一套string类型的类


class MinClass{
    public list:number[]=[];
    add(num:number){
        this.list.push(num)
    }
    min():number{
        var minNum=this.list[0]; for(var i=0;i<this.list.length;i++){ if(minNum>this.list[i]){ minNum=this.list[i]; } } return minNum; } } var m=new MinClass(); m.add(1); m.add(2); alert(m.min()); 

使用泛型之后:只用一套类来实现


class MinClassT<T>{
    public list:T[]=[];
    add(value:T):void{ this.list.push(value); } min():T{ var minNum=this.list[0]; for(var i=0;i<this.list.length;i++){ if(minNum>this.list[i]){ minNum=this.list[i]; } } return minNum; } } var m1=new MinClassT<number>(); /*实例化类 并且指定了类的T代表的类型是number*/ m.add(1); m.add(2); alert(m1.min()) var m2=new MinClassT<string>(); /*实例化类 并且指定了类的T代表的类型是string*/ m2.add('c'); m2.add('a'); alert(m2.min()) 

6.3 泛型接口

有一个函数类型接口


interface ConfigFn{
    (value:string):string;
}
var setData:ConfigFn = function(value:string):string{ return value } setData('name'); // setData(20); // 错误 

setData(20);写法错误,想要传入number类型的参数又要写一个函数类型接口 => 用泛型接口

泛型接口有两种写法:


// 泛型接口定义方式一
interface ConfigFnOne{
    <T>(value:T):T;
}
var setDataOne:ConfigFnOne = function<T>(value:T):T{ return value } // 既可以传入string也可以传入number类型参数 setDataOne<string>('name'); setDataOne<number>(20); 

// 泛型接口定义方式二
interface ConfigFnTwo<T>{
    (value:T):T;
}
function setDataTwo<T>(value:T):T{ return value } var setDataTwoFn:ConfigFnTwo<string> = setDataTwo setDataTwoFn('name'); 

Please see the sample code in github, welcomed Start  HTTPS: //github.com/dzfrontend ...

Guess you like

Origin www.cnblogs.com/zhuxinpeng-looking/p/11334986.html