typescript中的结构及类型系统

2022-12-04  本文已影响0人  成熟稳重的李先生
  1. 接口的兼容性
interface Animal {
    name: string;
    age: number;
}

interface Person {
    name: string;
    age: number;
    gender: number
}
// 要判断目标类型`Person`是否能够兼容输入的源类型`Animal`
function getName(animal: Animal): string {
    return animal.name;
}

let p = {
    name: 'zhufeng',
    age: 10,
    gender: 0
}

getName(p);  // 不报错,因为p有name和age属性
//只有在传参的时候两个变量之间才会进行兼容性的比较,赋值的时候并不会比较,会直接报错
let a: Animal = {  //不报错,原因同上
    name: 'zhufeng',
    age: 10,
    gender: 0
}
  1. 基本类型的兼容性
let num: string | number;
let str: string = "zhufeng";
num = str;
let num2: {
    toString(): string
}
let str2: string = "abc";
num2 = str2; //这里不报错的原因如上
  1. 类的兼容性
    class Animal {
        name: string
    }
    class Bird extends Animal {
        swing: number
    }
    let a: Animal;
    a = new Bird(); //赋值成功,因为Bird实例中有name属性
    let b: Bird;
    b = new Animal(); //赋值失败,Animal实例中没有swing属性
    // 如果子类没有自己的属性(即父子拥有相同属性)
    class Tiger extends Animal {}
    let c: Tiger;
    c = new Animal(); //赋值成功,因为tiger只有name属性,而Animal实例中有此属性
    // 甚至两个没关系的类,只要属性相同,便能赋值
    class Person {
        name: string
    }
    let p: Person;
    p = new Animal()
  1. 函数的兼容性
type sumFunc = (a:number,b:number)=>number;
let sum:sumFunc;
function f1(a:number,b:number):number{
return a+b;
}
sum = f1;

//可以省略一个参数
function f2(a:number):number{
 return a;
}
sum = f2;

//可以省略全部参数
function f3():number{
  return 0;
}
sum = f3;

//多一个参数就不行了
function f4(a:number,b:number,c:number){
  return a+b+c;
}
sum = f4;

4.2 比较返回值

type GetPerson = ()=>{name:string,age:number};
let getPerson:GetPerson;
//返回值一样可以
function g1(){
    return {name:'lc',age:10};
}
getPerson = g1;
//返回值多一个属性也可以
function g2(){
    return {name:'lc',age:10,gender:'male'};
}
getPerson = g2;
//返回值少一个属性可不行
function g3(){
    return {name:'lc'};
}
getPerson = g3;
//因为有可能要调用返回值上的方法
getPerson().age.toFixed();
  1. 函数参数的协变
let sourceFunc = (args: number | string) => { }
let target1Func = (args: number | string) => { }
let target2Func = (args: number | string | boolean) => { }
sourceFunc = target1Func;
sourceFunc = target2Func;
  1. 接口的兼容性
enum EventType {
    MouseEvent
}
interface Event {
    timestamp: number
}
interface MouseEvent extends Event {
    pageX: string,
    pageY: string
}
function addEventListener(eventType: EventType, handler: (event: Event) => void){

}
// MouseEvent可以赋值给event类型
addEventListener(EventType.MouseEvent, (event: MouseEvent) => {
})
  1. 泛型的兼容性
 //接口内容为空没用到泛型的时候是可以的
//1.接口内容为空没用到泛型的时候是可以的
interface Empty<T>{}
let x!:Empty<string>;
let y!:Empty<number>;
x = y;  //成功
相当于 x = {}, y = {},因此,赋值成功

//2.接口内容不为空的时候不可以
interface NotEmpty<T>{
  data:T
}
let x1!:NotEmpty<string>;
let y1!:NotEmpty<number>;
x1 = y1;// 报错
//相当于 x1 = { data:string=undefined }, y1 = {data:number = undefined}


//实现原理如下,称判断具体的类型再判断兼容性
interface NotEmptyString{
    data:string
}

interface NotEmptyNumber{
    data:number
}
let xx2!:NotEmptyString;
let yy2!:NotEmptyNumber;
xx2 = yy2;


let xx3!:NotEmpty<number>;
let yy3!:NotEmpty<number | string>;
xx3 = yy3; //报错
yy3 = xx3; //成功
  1. 枚举的兼容性
//数字可以赋给枚举
enum Colors {Red,Yellow}
let c:Colors;
c = Colors.Red;
c = 1;  //成功
c = '1';  //报错

//枚举值可以赋给数字
let n:number;
n = 1;
n = Colors.Red;

enum specialColos{Red, Yellow}
c = specialColos.Red //报错,不同枚举之间不能相互赋值
上一篇下一篇

猜你喜欢

热点阅读