阅读 94

TypeScript 中的对象类型、类型推论-对象、复杂的对象

对象的类型

image-20210930150053741.png

接下来,我们来看下这样一个例子:

// 定义接口,一般使用首字母大写 interface Person {     name: string;     age: number; } // 将这个变量约束为这个接口的格式,定义 name 和 age 的时候,也必须要满足接口要求的类型 let alex: Person = {     name: 'Alex',     age: 20 } 复制代码

添加接口的时候,可以使用分号或者逗号分隔每一项,当然也可以什么都不加。

需要注意的是,如果我们的变量缺少某一项属性,那么它就会报错

当然,多余某一项属性,同样也会报错的。

// 缺少某一项属性 interface Person {     name: string;     age: number; } let alex: Person = {     name: 'Alex' } // 多余某一项属性 interface Person {     name: string;     age: number; } let alex: Person = {     name: 'Alex',     age: 20,     gender: 'male' } 复制代码

但是有些时候,我们希望这样一个接口,它的某些属性是可选的。我们可以加上一个问号。

// ?: 表示为可选的,将这一条属性标为可选属性 interface Person {     name: string;     age?: number; } let alex: Person = {     name: 'Alex' } 复制代码

有些时候,我们无法无法预知它有什么新的属性。这个时候,我们就需要用到任意属性了。

需要注意的是:

  • 任意属性,必须要包含上面的所有的数据类型,针对上面那个报错,使用联合类型处理

  • propName 可以改成其他名字,比如 x 或者 y

interface Person {     name: string;     age?: number;     // [propName: string]: any; // 正常     // [propName: string]: string; // 报错     // 任意属性,必须要包含上面的所有的数据类型,针对上面那个报错,使用联合类型处理     [propName: string]: string | number; } let alex: Person = {     name: 'Alex',     gender: 'male' } 复制代码

习题:变量 animal 可以声明为哪些类型?

const animal: _____ = {     weight: 10,     isMammal: true } 复制代码

A. any

B. number | boolean

C. { number | boolean }

D. { weight: number; isMammal: boolean; }

答案

A D

解析

变量 animal 被赋值为对象,因此变量 animal 应该声明为具体的对象类型。

  • A - 任何不确定类型的变量都可以声明为 any,故正确。

  • B - 本选项的联合类型中均为基本数据类型。故错误。

  • C - 错误的写法。

  • D - 本选项为一个对象类型,且结构类型与赋值对象结构类型相符,故正确。

资料:只读属性

在日常的开发过程中,由于多人协作或者项目较为复杂等因素造成对象的值被重写,从而导致 bug 产生的情况时常发生。所以在编码阶段能够检测到此类错误并阻止通过编译显得尤为重要。恰好,TypeScript 为我们提供了这种能力,我们可以用 readonly 定义只读属性:

interface Person {     readonly id: number;     name: string;     age?: number;     [propName: string]: any; } let tom: Person = {     id: 89757,     name: 'Tom',     gender: 'male' }; tom.id = 9527; // index.ts(14,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property. 复制代码

上例中,使用 readonly 定义的属性 id 初始化后,又被赋值了,所以报错了。

注意,只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候:

interface Person {     readonly id: number;     name: string;     age?: number;     [propName: string]: any; } let tom: Person = {     name: 'Tom',     gender: 'male' }; tom.id = 89757; // index.ts(8,5): error TS2322: Type '{ name: string; gender: string; }' is not assignable to type 'Person'. //   Property 'id' is missing in type '{ name: string; gender: string; }'. // index.ts(13,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property. 复制代码

上例中,报错信息有两处,第一处是在对 tom 进行赋值的时候,没有给 id 赋值。

第二处是在给 tom.id 赋值的时候,由于它是只读属性,所以报错了。

类型推论 - 对象

接着前面的例子,继续学习类型推论,在对象中是怎样的?

interface Person {     name: string;     age?: number;     [propName: string]: string | number; } let alex: Person = {     name: 'Alex',     gender: 'male' } 复制代码

把类型定义,直接放到变量定义的地方呢?这样的话,我们就可以省掉 interface

let alex: {     name: string;     age?: number;     [propName: string]: string | number; } = {     name: 'Alex',     gender: 'male' } 复制代码

现在 alex 就是后面定义的类型。如果我们把后面定义的这一串类型,全部省掉的话。

这时候的 alex,就会根据它的值,自动推论出类型。

image-20211009221128564.png

复杂的对象

前面我们学习的都是简单的对象,包含一个层级,那如果这个对象,包含多个层级呢?ts 该怎么去描述它?

let alex: Person = {     name: 'Alex',     gender: 'male',     friend: {         name: 'Lucy',         age: 18     } } 复制代码

那能不能在 interface 直接这样描述呢?答案是可以的。

interface Person {     name: string;     gender: string;     friend: { // 对象结构         name: string;         age: number;     } } // 这样就可以正确描述 alex 类型了 let alex: Person = {     name: 'Alex',     gender: 'male',     friend: {         name: 'Lucy',         age: 18,         // gender: 'female' // 报错     } } 复制代码

习题:在严格类型模式下,变量 animal 的类型

const animal = {     weight: 10,     isMammal: true } 复制代码

A. any

B. number | boolean

C. { number | boolean }

D. { weight: number; isMammal: boolean; }

答案:D

解析

变量 animal 被赋值为对象,因此变量 animal 会被推论为具体的对象类型。

  • A - any 不是具体的对象类型,故错误。

  • B - 本选项的联合类型中均为基本数据类型。故错误。

  • C - 错误的写法。

  • D - 本选项为一个对象类型,且结构类型与赋值对象结构类型相符,故正确。


作者:追梦玩家
链接:https://juejin.cn/post/7028052814815297549


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐