Typestript核心——接口interface,类类型,类接口,继承接口

发布于:2023-01-20 ⋅ 阅读:(20) ⋅ 点赞:(0) ⋅ 评论:(0)

TypeScript的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。
一般做法就是在变量的名,参数名,函数名后面需要添加类型,这个类型添加的方法就是在其后面加:数据类型,也就是添加约束。

一、普通方法定义对象属性

var obj: { a: number, B: string, c: boolean } = { a: 1, B: "a", c: true }
console.log(obj);
var obj1: { a: number, b: { c: number, d: Array<number> } } = { a: 2, b: { c: 4, d: [1, 2, 3] } }
console.log(obj1);

二、通过关键字interface来定义接口(数据类型)

interface IObj {
    a: number,
    b: {
        c: number,
        d: Array<number>
    }
}

var obj2: IObj = { a: 2, b: { c: 2, d: [1, 2, 3] } }

三、函数参数以及返回值的数据类型(函数类型)

第一种统一使用Function,无法知道函数的参数和返回

 var fn:Function=function fn(a: number): void {

}

第二种直接定义,使用(参数)=>返回类型 这种方式,因为前面已经有了:所以后面的返回值使用=>

var fn: (a: number) => void = function (a: number): void {

}

第三种独立定义接口函数(参数):返回数据类型

interface IFn {
    (a: number): void
}

var fn: IFn = function (a: number): void {

}

第四种类型,如果在对象中的函数,函数是有名称的,直接使用函数名(参数类型):返回值类型

interface Ifn {
    a: number,
    // b: (a: number) => void,
    b(a:number):void

}

var obj:Ifn={
    a:1,
    b:function(a:number):void{

    }
}

四、可选属性

接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。
带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?符号。
可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误。

对象
var obj: { a: number, b?: number } = { a: 1 }
声明式函数
function fn(a:number,b?:number):void{

}
对象中的函数
interface IObj {
    a:number,
    //一旦对象中这个方法可选,则必须使用?:(参数)=>返回类型
    c?: (a: number) => void
}
var obj:IObj = {
    a:3,
    c:function(a:number):void{

    }
}

五、只读属性

interface Point {
    readonly x: number;
    readonly y: number;
}
var p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!

六、根据代码写字面量接口

var obj:Iobj={
    // a属性必须只读
    a:1,
    b:[{a:1,b:2},{b:3,c:4},{a:3,c:6}],
    c:{
        d:function(a:number,b?:number)
        {
            return a+1;
        },
        // 这个函数可有可无
        e:function(){

        }
    }
}

按要求创建以上代码的一个对象字面量接口
interface Iobj {
    readonly a: number,
    b: Array<{ a?: number, b?: number, c?: number }>,
    c: {
        d: (a: number, b: number) => number
        e?: () => void
    },
    
}

七、额外属性,对象可自由添加属性

也就是对所有的属性类型做一个统一标准,而且是最高的标标准。
注意不要和可索引的类型混淆

var obj: { [key: string]: number } = {};

obj.a =12
obj.c =89
console.log(obj);//{a: 12, c: 89}
interface Iobj{
    // a:string
    //遵循最高标准额外属性
    [key:string]:number;
}
var obj:Iobj = {
    a:9,
    b:2
} 

八、索引属性

这样专指数组
var arr:Array<{a:number,b:number}>=[{a:1,b:2},{a:2,b:3}];
通过创建字面量接口
interface IArr{
    [index:number]:{a:number,b:number};
}
这样要是列表类型的也可以检测,包括数组
var arr:IArr=[{a:1,b:2},{a:2,b:3}];

九、类类型:类的类型

——实现接口

类如果实现某个接口(契约),那么这个类就必须有这个接口属性和方法。
那么它就是针对这个类去约束,约定实现implements接口的某些规定。
把两个没有关系的类加一个关系,进行共同处理

创建一个接口,规定必须有updata方法,返回值为void
interface Iop {
    updata(): void
}
class Box implements Iop{
    updata(): void {
        console.log("Box");
        
    }
}
class Ball implements Iop{
    updata(): void {
        console.log("Ball");
    }
}
var b:Box=new Box();
var c:Ball=new Ball();
var b:Box=new Box();
var c:Ball=new Ball();

如果将生成的对象放在这个数组中
var arr:Array<Box|Ball>=[b,c];
以接口为类型描述数组元素
var arr:Array<Iop>=[b,c];

遍历数组,这个item添加接口描述
arr.forEach((item:Iop)=>item.updata())

一个类。可实现多个接口,即可处理多种关系

interface IA{
    a:number;
    play():void;
}

interface IB{
    b:number;
    run():void;
}
interface IC{
    c:number;
}
class Box implements IA,IB{
    a:number=1;
    b:number=2;
    constructor(){

    }
    run(): void {
        
    }
    play(): void {
        
    }
    
}

class Ball implements IA,IC
{
    a:number=2;
    c:number=2;
    constructor(){

    }
    play(): void {
        
    }
}

var arr:Array<IA>=[new Box(),new Ball()];

十、类接口

通过一个接口,让类实现接口,从而让各类之间有关系
这里的 IUpdate 类型就是一种相同的联系

interface IUpdate{
    update():void;
}

class Box implements IUpdate{
    constructor(a:number){

    }
    update():void{

    }
}

class Ball implements IUpdate{
    constructor(a:number){

    }
    update():void{

    }
}
在这里使用 new ()的接口意味着是一个构造函数,这个构造函数new出的实例化对象我不确定,但是他们都是IUpdate类型

interface ID{
    /* new 了之后才返回IUpdate */
    new (a:number):IUpdate;
}

/* 目的是传入一个参数为类名,返回一个对应的实例 */
function fn(className:ID):IUpdate{
    var d:IUpdate=new className(3);
    return d;
}
将类名作为参数传入
目的是传入一个参数为类名,返回一个对应的实例
console.log(fn(Box));
console.log(fn(Ball));

后面有泛型讲解,原理一样

十一、继承接口

类实现
interface IA{
    a:number;
}

interface IB extends IA{
    b:number;
}
class Box implements IB{
    b:number=1;
    a:number=2;
}


对象约束
interface IA{
    a:number;
}

interface IB extends IA{
    b:number;
}
var obj:IB = {
    b:1,
    a:2
}

十二、接口继承类

接口只是把属性名和属性类型拿过来了。并没有把属性值(实现内容)拿过来。
注意别和类的继承搞混淆

class Box{
    a:number=1;
    b:number=2;
    play():void
    {
        console.log("play")
    }
}

接口IA继承Box类的属性和属性类型

interface IA extends Box{
    c:number;
}

class Ball implements IA{
    c:number=1;
    a:number=2;
    b:number=3;
    play():void
    {
        console.log("cc");
    }
}

十三、混合类型

interface IB {
    (a: number): number;
    a: number;
}
function fn():IB{
    /* <IB>如果不写,说明不了这个返回值是一个IB类型 */
    var f:IB = <IB> function(a:number):number{
        return a;
    }
    f.a = 10;
    return f;
}