typescript中的结构及类型系统

  1. 接口的兼容性
  • 如果传入的变量和声明的类型不匹配,TS就会进行兼容性检查
  • 原理是Duck-Check(一个对象,只要它会鸭子叫,那就当它是鸭子),就是说只要目标类型中声明的属性变量在源类型中都存在就是兼容的
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. 基本类型的兼容性
  • 基本类型,如string,number等等,在调用它们自身的方法时,会隐式的将其变成对应的包装类型,用完销毁。因此在调用string.toString(),string.length,number.toFixed(2)时,能正常拿到结果
let num: string | number;
let str: string = "zhufeng";
num = str;
let num2: {
    toString(): string
}
let str2: string = "abc";
num2 = str2; //这里不报错的原因如上
  1. 类的兼容性
  • 在TS中是结构类型系统,只会对比结构而不在意类型(只看是否有某一方法或者属性,并不判断类型)
    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. 函数的兼容性
  • 比较函数的时候是要先比较函数的参数,再比较函数的返回值
    4.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. 函数参数的协变
  • 当比较函数参数类型时,只有当源函数参数能够赋值给目标函数或者反过来时才能赋值成功
  • 需要将tsconfig.json中的"strictFunctionTypes"设置为false
let sourceFunc = (args: number | string) => { }
let target1Func = (args: number | string) => { }
let target2Func = (args: number | string | boolean) => { }
sourceFunc = target1Func;
sourceFunc = target2Func;
  1. 接口的兼容性
  • 接口和类的兼容性类似,a接口包含b接口,那么a就可以赋值给b
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 //报错,不同枚举之间不能相互赋值
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容