Typescript基础知识点总结

119 阅读8分钟

1. 各类型定义

1.1 类型定义

let  flag:boolean  = false //  布尔类型
let num:number = 3 // 数值类型
let str:string = 'abc'  // 字符串类型
let u:undefined = undefined 
let n:null = null
void类型 // 用于定义无返回的函数

1.2 任意值

如果一个普通类型,在赋值过程中改变类型是不允许的,任意类型any表示允许赋值为任意类型。

let a2:any = 'abc'
a2 = 7 // 允许

// 如果声明时未指定类型,那么会被识别为any类型
let a3;
a3 = 'abc'
a3 = 7

1.3 联合类型

表示取值可以为多种类型的一种

let a:string|number;
a=4
a='abc'

function getLength(str:string|number):number{
    return str.length // 报错,为什么?
}
// 当 TypeScript不确定一个联合类型的变量到底是哪个类型的时候
// 只能访问此联合类型的所有类型里共有的属性或方法
function getLength(str:string|number[]):number{
    return str.length
}
console.log(getLength([1,2,3])

1.4 数组类型

// 用「类型 + 方括号」来表示数组
let arr:number[] = [1,2,3]
let arr:string[] = ['a','b','c']

// 泛型:是指在定义函数、接口或类的时候,不预先指定具体的类型,
// 而在使用的时候再指定类型的一种特性
let arr:Array<number> = [1,2,3]
let arr:Array<number|string> = ['a',1,2]

1.5 函数类型的定义

  • 输入类型
  • 输出类型
// 返回number
function sum(x:number,y:number):number{
    return x + y
}
// 返回boolean
function f2(n1:number,n2:number):boolean{
    if(n1>n2){
        return true;
    }else {
        return false;
    }
};
// 无返回值
function f3(n1:number,n2:number):void{  
    if(n1>n2){
        //....
    }else {
        //...
    }
};
// 参数默认值
function sum(x:number=5,y:number):number{
    return x + y
}
// 参数默认值编译后如下:
function sum(x, y) {
    if (x === void 0) { x = 5; }
    return x + y;
}
console.log('sum:', sum(void 0, 2)); // 5 + 2 =7

// 可选参数
function sum(x:number,y?:number):number[] {
    return [x,y]
}
let s2 = sum(1) // [1,undefined]

// 函数表达式
let sum = function(x:number,y:bumber):number{
    return x + y
}
// 箭头函数
let sum = (x:number,y:number):number => {
    return x + y 
}

1.6 类型别名

type n  = string|number[]
let fn = (s:n):number => {
    return s.length
}

2. 类

2.1 构造函数

// 构造函数
function Cat(name.color) {
    this.name = name;
    this.color = color;
}
// 原型
Cat.prototype.type='动物';
Cat.prototype.eat = function () {
  return console.log("吃老鼠");
};
var cat1 = new Cat("大明","黄色");
var cat2 = new Cat("小明","白色");

2.2 定义类

class Cat {
    name: string
    color: string
    constructor(name:string,color:string) {
        this.name = name
        this.color = color
    }
    eat (param: string):string {
        return '吃老鼠'
    }
}
let cat:Cat = new Cat('小花','white')

2.3 类的继承

class Animal {
    name:string;
    constructor(name:string){
        this.name = name
    }
    eat(){
        console.log('吃肉')
        return '吃肉'
    }
}
// 继承
class Dog  extends Animal {
    constructor(name:string){
        super(name) // 调用父类的constructor(name) //Animal.prototype.constructor.call(this);
    }
    sayHi(){
        return `${this.name}:${this.eat()} ` // 调用父类的eat方法
    }
}

let dog:Dog = new Dog('tom')
dog.sayHi()

2.4 修饰符

  • 修饰符是用于限定类型以及类型成员声明的一种符号。
  • static 使用修饰符static修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用:
  • public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的;
  • private 修饰的属性或方法是私有的,不能在声明它的类的外部访问;
  • protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的;
 // static  使用修饰符static修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用:
class Obj1{
    name:string;
    constructor(name){
        this.name = name;
    }
    static action(state:string):string{
        return state;
    }
};
let o1 = new Obj1("Tom");   //实例化
o1.action("play"); // 报错
Obj1.action("play"); //不需要实例化,而是直接通过类来调用

 // public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的;
class Obj2{
    public name:string;
    public constructor(name){
        this.name = name;
    }
    public action(state:string):string{
        return state;
    }
};
let o2 = new Obj2("Tom");   //实例化
o2.name;
o2.action('sing');

// private 修饰的属性或方法是私有的,不能在声明它的类的外部访问;
class Obj3{
    private name:string;
    public constructor(name){
        this.name = name;
    }
    private action(state:string):string{
        return state = this.name;
    }
};
let o3 = new Obj3("Tom");
o3.name;  //不能访问
o3.action('play'); //不能访问

// protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的;
class Obj4{
    protected name:string;
    public constructor(name){
        this.name = name;
    }
    protected action(state:string):string{
        return state = this.name;
    }
};
let o4 = new Obj4("Jack");
o4.name; // 提示错误,只能Obj4 和它的子类访问
o4.action("sing"); // 提示错误,只能Obj4 和它的子类访问

2.5 类实现接口

interface IFeatures {
    name?:string;
    age:number;
    height?:number;
    weight?:number;
    action():string;
}

//类受到接口的约束   类实现接口
class Person implements IFeatures {
    name:string;
    age:number;
    constructor(name,age){
        this.name=name;
        this.age = age;
    }
    action(){
        return '哭';
    }
};
let p1 = new Person('abc',18);

// 有时候不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口(interfaces),
// 然后类用 implements 关键字来实现接口
interface IAlarm{
    sing();   
}

interface Light {
    lightOn();
    lightOff():boolean;
   }

class Door {

}

// 子类继承父类并实现接口
class SecurityDoor extends Door implements IAlarm{
    sing(){console.log('134424')}
}
// 类实现多个接口
class Car implements IAlarm , Light{
    sing(){}
    lightOn(){}
    lightOff(){ return true}
}

2.6 类和接口区别

  • 一、表示内容不同
  1. 抽象类:抽象类表示该类中可能已经有一些方法的具体定义。
  2. 接口:接口就仅仅只能定义各个方法的界面(方法名,参数列表,返回类型),并不关心具体细节。
  • 二、性质不同
  1. 抽象类:抽象类是对象的抽象。
  2. 接口:接口是一种行为规范。

3. 接口

3.1 对象的类型-接口

接口是对行为的抽象

接口(Interfaces)可以用于对「对象的形状(Shape)」进行描述

// 接口定义
interface Person {
    name:string;
    age:number;
    sex?:string|number; //可选属性
    [propName:string]:any; //任意属性
}
let tom:Person = {
    name: 'tom',
    age:18,
    hobby:'sing'
}
// 上面,我们定义了一个接口 Person,接着定义了一个变量tom,它的类型是 Person。
// 这样,我们就约束了 tom 的形状必须和接口 Person 一致。

  • 定义的变量比接口少了一些属性是不允许的
  • 可选属性:例如(sex?:string|number;)可选属性的含义是该属性可以不存在。这时仍然不允许添加未定义的属性
  • 任意属性 :例如( [propName:string]:any;)一个接口允许有任意的属性,确定属性和可选属性都必须是任意属性的子属性

3.2 接口在函数中运用

interface IMsg{
    id:number;
    msg:string;
}

function f1(obj:IMsg):number {
    return obj.id
}

let obj = {id:1,msg:'hello'};
f1(obj);
// f2 和f3 参数类型有共性和返回值
function f2(a:string,b:string):boolean{
    return a==b
};

function f3(s1:string,s2:string):boolean{
    if(s1<s2){
        return true;
    }else {
        return false;
    }
}
// 于是,可以定义接口
interface IinspectFunc {
    (x:string,y:string):boolean
}

// 重新调整一下f2,f3
let f2:IinspectFunc = (a,b) => {
    return a  == b
}
let f3:IinspectFunc = function(a,b) {
    if(a < b){
        return true;
    }else {
        return false;
    }
}

3.3 接口使用泛型

interface IinspectFunc{
    <T>(x:T,y:T):boolean
}

let f1:IinspectFunc = (a,b) => a === b
f1<number>(1,2)  // 调用f1

//  第二种写法:泛型参数提前到接口名上
interface  IinspectFunc<T>{
    (x:T,y:T):boolean
}
let f1:IinspectFunc<number> = (a,b) => a === b
f1(1,2) // 调用

4. 泛型

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

4.1 什么时候需要定义泛型函数

要创建一个可重用的组件,其中的数据类型就必须要兼容很多的类型

// 定义一个只能传入number类型的函数
function f(a:number,b:number):number[]{
     return [a,b]
}
f(1,2);
// 定义一个只能传入string类型的函数
function f2(a:string,b:string):string[]{
     return [a,b]
}
f2('1','3')

// 泛型函数
function f3<T>(a:T,b:T):T[]{
    return [a,b]
}
f3<number>(1,2)
f3<string>('a','b')

4.2 不使用泛型

function f6<T>(n1:T,n2:T):T {
    return n1+n2  //错误   并不是所有的类型都有+连接符
};
f6<number>(10,20)

function f8<T>(str:T):number {
    return str.length  //错误,并不是所有的类型都有.length属性
};

4.3 泛型类型

// 函数声明
function mySum<T>(a:T,b:T):T[]{
    return [a,b]
}

// 函数表达式
let mySum = function<T>(a:T,b:T):T[]{
    return [a,b]
}

// ES6 箭头函数
let mySum = <T>(a:T,b:T):T[] => [a,b]

4.4 泛型约束

interface IlengthN{
    length:number
}
let fn  = <T extends IlengthN>(n:T):number => n.length
fn<string>('abcd')

4.5 泛型接口

//定义一个函数,传入长度和具体的值,返回数组(数组的长度传入的长度,数组的值传入的值)
function createArray<T>(length:number,value:T):Array<T> {
    let arr = [];
    for(let i=0;i<length;i++){
        arr[i] = value;
    };
    return arr;
};
createArray<string>(3,'x'); //['x','x','x'];

//扩展一
//定义接口
interface ICreateArrayFun {
    <T>(length:number,value:T):Array<T>
};
let createArray2:ICreateArrayFun = function<T>(len,v){
    let arr:T[] = [];
    for(let i=0;i<len;i++){
        arr[i] = v;
    };
    return arr;
};
createArray2<string>(3,'x'); //['x','x','x'];


//扩展二   value参数类型中必须包括length属性
interface IlengthN3 {
    length:number;
};
interface ICreateArrayFun3<T extends IlengthN3> {   //泛型约束
    (length:number,value:T):Array<T>
};
// 写法2
// interface ICreateArrayFun3 {
//     <T extends IlengthN3>(length:number,value:T):Array<T>
// };
let createArray3:ICreateArrayFun3<number[]> = function(len,v){
    let arr = [];
    for(let i=0;i<len;i++){
        arr[i] = v;
    };
    return arr;
};
createArray3(3,[123]); //['x','x','x'];

4.6 泛型在类中运用

class Obj<T>{
    state:T;
    constructor(state:T){
        this.state = state;
    }
    action(s:T):T{
        return s;
    }
};
let o = new Obj<string>('Tom');

//多个类型参数
function fun<N,S>(sum:[N,S]):[S ,N] {
    return [sum[1],sum[0]]
};
fun<number,string>([1,'a'])