TypeScript学习(四):对象的定义及使用

前面我们说到了数据类型,像什么布尔类型,数值类型,字符串类型等等,在开发中,我们还会遇到很多像对象、数组、函数等类型,那么在typescript中是怎么定义这些类型的?

对象(object)

我们先介绍下在JavaScript中式怎么定义对象的,在我之前的博客中有提到关于原型链的理解,那里面有对于对象的构造函数-实例对象-原型对象的一个介绍(浅谈我对原型链的理解),这里我再简单说一下,在JavaScript中我们定义对象方式如下:

var person = {
  name: 'zhangsan',
  age: 18,
  sayName: function () {
    console.log(this.name)
  }
}

可以看到我们创建了一个人物对象,包含人物的姓名,年龄及行为,并且在JavaScript中我们可以随意调用该人物的属性以及随意添加任务新属性,例如:

console.log(person.name);       // 获取人物的姓名
console.log(person.age);        // 获取人物的年龄
console.log(person.sayName());  // 调用人物的行为

person.gender = 'male';         // 给人物添加新的性别属性

那么在typescript中我们是如何定义对象呢?又是如何获取对象中的属性和定义新的属性呢?

在typescript中,我们定义对象的方式要用到接口,即Interfaces(接口),定义方式如下:

// 我们先定义一个对象的属性,需要注意的是我们使用接口interface定义对象时,接口的首字母最好是大写
interface Person {
    name : string ,
    age: number
}

我们刚刚定义了一个Person类型的对象,它包含姓名(值类型为字符串类型)和年龄(值类型为数值类型),我们使用方式如下:

let zhangsan : Person {
    name : 'zhangsan',
    age : 25
}

可以看到,我们定义了一个变量zhangsan,给他定义一个我们创建好的Person类型,同时给属性name和age赋值,这样定义和使用是没有任何问题的,但是,typescript中,我们定义和使用对象属性时需要注意以下几种情况:

(1)使用的类型与定义的类型不一致,例如缺少属性或者新增属性,在typescript中是不允许的,如下:

interface Person {
    name : string ,
    age: number
}

// 缺省属性
let zhangsan : Person {
    name : 'zhangsan'
};

// 新增属性
let zhangsan : Person {
    name : 'zhangsan',
    age : 25,
    weight : 75
};

以上两种情况下,编译均会报错,所以我们可以得知,在typescript中使用的类型与定义的类型必须保持一致,属性不能多也不能少。

但是,这样很不方便,因为我们不知道定义的变量在实际开发中会附上哪些属性,所以typescript中提供了一种方法,也就是任意属性,如下:

interface Person {
    name : string , 
    [propName: string] : any;
}
let zhangsan : Person {
    name : 'zhangsan',
    gender : 'male' 
};

上面我们定义了一个任意属性,而且编译没有报错,证明我们的代码是没有问题的,不过,这里的任意属性的定义,还有一个值得注意的地方,先看代码:

interface Person {
    name : string , 
    age : number ,
    [propName: string] : any;
}
let zhangsan : Person {
    name : 'zhangsan',
    age : 25 ,
    gender : 'male' 
};

这时候你运行代码,会发现报错了:’Property ‘age’ of type ‘number’ is not assignable to string index type ‘string’.’,这报错的意思,我们从字面理解的话就是:’类型为“number”的属性“age”不能分配给字符串索引类型“string”。’,我们再深入理解,也就是属性age的number属性不是string类型的子属性。这样就很奇怪了,为什么会报这个错误?

我们可以看下官方文档,原来如果我们在定义接口对象时定义了任意属性,那么这个接口对象内其余的属性就必须是任意属性的子属性,因为我们定义了一个age属性,它的类型是number类型的,而number类型不是string类型以及它的子类型,所以编译时就报错了。

(2)有的类型我们可能用不上,不想去定义,例如性别分为男女,但是还有外星人(当然这里只是调侃一下),这个时候我们不需要性别属性,我们该如何定义?如下:

interface Person {
    name : string ,
    age: number ,
    gender ? : string
}

let zhangsan : Person {
    name : 'zhangsan' ,
    age : 25
}

可以看到,我们并没有使用Person接口对象内的gender属性,但是编译的时候也没有报错,也就是说gender属性在使用时可有可无。

(3)只可读属性,如下:

interface Person {
    name : string ,
    age : number ,
    readonly id: number
}

在这里我们定义了Person接口对象的属性id为只可读属性,所以我们在初始化变量后,就不能再更改此属性,例如:

interface Person {
    name : string ,
    age : number ,
    readonly id: number
}

let zhangsan: Person = {
    name: 'Tom' ,
    age: 25 ,
    id: 1
};

zhangsan.id = 2;   // 编译报错:Cannot assign to 'id' because it is a constant or a read-only property.

这里需要注意一个地方,我们在定义只可读属性时,约束存在于第一次给对象赋值的时候,也是说约束存在于第一次let zhangsan : Person中,而单独赋值(zhangsan.xxxxx)时是不允许的。

 

 

到底啦!!!!!!!!

    原文作者:Bean.Cooker
    原文地址: https://blog.csdn.net/Kreme/article/details/102699712
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞