TypeScript中的对象类型(可选属性 只读属性 交叉类型)

2023-11-14

一、定义对象类型

在TypeScript中定义对象类型有以下三种方式:

1. 匿名对象类型

匿名对象类型是在定义变量时直接使用花括号{},来定义一个对象类型。例如:

const person: { name: string, age: number } = { name: 'John', age: 25 };

上述代码中定义了一个person变量,它的类型为对象,它有两个属性:name和age,其中name属性的类型为字符串,age属性的类型为数字。

2. 接口类型

使用接口来定义对象类型,可以使代码更加可读、易于维护。例如:

interface Person {
  name: string;
  age: number;
}

const person: Person = { name: 'John', age: 25 };

上述代码中,定义了一个名为Person的接口,其中包括了两个属性:name和age。然后使用Person接口来定义了一个person变量,它的类型为Person接口。

3. 类型别名

使用类型别名可以为对象类型定义简短、易读的名称。例如:

type Person = {
  name: string;
  age: number;
}

const person: Person = { name: 'John', age: 25 };

上述代码中,使用type关键字定义了一个名为Person的类型别名,并通过花括号{}来定义了一个对象类型,其中有两个属性:name和age。然后使用Person类型别名来定义了一个person变量,它的类型为Person类型别名。

二、对象类型中的属性修改器

1. 可选属性

TypeScript中的可选属性指的是,在定义对象类型时,可以设置一些属性为可选属性,即不是必须存在的属性。具体的语法是在属性名称后面加上一个问号(?),如下所示:

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

在上面的例子中,agegender是可选属性。也就是说,在声明一个Person类型的对象时,可以只包含name属性,而不必提供agegender属性。如果提供了这两个属性,它们的值必须符合对应的类型定义。

下面分多个角度举例说明可选属性的用法和好处。

(1). 增强代码的灵活性

使用可选属性可以增强代码的灵活性,使得我们在声明对象的时候可以根据需要选择性地添加属性,而不是强制要求属性必须存在。这样一来,一些在某些场景下没有用处的属性就不必被强制赋值了,节约了代码修改的时间和精力。

举个例子,我们在定义一个Book接口时,可以将authorpublisherdescription属性都定义为可选属性:

interface Book {
  title: string;
  author?: string;
  publisher?: string;
  description?: string;
}

然后在使用这个接口定义对象的时候,可以按照需求来添加这些属性,比如:

const book1: Book = {
  title: 'TypeScript in Action',
  author: 'Erick Wendel'
};

const book2: Book = {
  title: 'JavaScript: The Good Parts',
  author: 'Douglas Crockford',
  publisher: 'Yahoo Press'
};

const book3: Book = {
  title: 'JavaScript: The Definitive Guide',
  author: 'David Flanagan',
  description: 'This book provides a complete description of the JavaScript language.'
};

在以上例子中,我们在声明book1时只提供了titleauthor属性,因为它们是必需的属性。而在声明book2时,我们增加了publisher属性,因为这个属性在这个场景下是有用的。在声明book3时,我们只提供了titleauthor属性,同时利用了description属性来描述这本书的内容。所以,这样的语法是非常方便的。

(2). 构建可靠的对象类型检查

使用可选属性还能帮助我们构建可靠的对象类型检查。

在JavaScript中,我们会遇到无效的对象属性,因为它们没被正确地定义或被更新。这些错误通常很难发现,结果会导致代码崩溃或是运行出现错误。

TypeScript可以用类型检查来防止这种问题。通过定义对象属性为可选属性,我们可以预防掉对象属性定义时的错误,从而构建可靠地类型检查系统。如果属性被定义成可选的,那么它可以没有定义,而且也不会触发错误。这样我们就可以更容易地处理这些异常情形,从而提高代码的可靠性和维护性。

下面是一个例子展示了使用可选属性来保证类型检查的可靠性:

interface Car {
  brand: string;
  model: string;
  year?: number;
}

function getCarInfo(car: Car): string {
  return `Brand: ${car.brand}, Model: ${car.model}${car.year ? `, Year: ${car.year}` : ''}`;
}

const car1: Car = { brand: 'Tesla', model: 'Model S', year: 2018 };
const car2: Car = { brand: 'BMW', model: 'X5' };
const car3: Car = { brand: 'Mercedes', model: 'E220', year: '2021' };

console.log(getCarInfo(car1)); // Brand: Tesla, Model: Model S, Year: 2018
console.log(getCarInfo(car2)); // Brand: BMW, Model: X5
console.log(getCarInfo(car3)); // Brand: Mercedes, Model: E220

在上面的例子中,我们定义了一个Car接口,并定义year属性为可选属性。可以清晰地看到,我们在getCarInfo函数中使用了year属性的值来返回车的信息。当year属性可选时,我们在获取year属性时需要先检查它是否存在,否则输出的字符串结果将不符合我们预期。在car3的定义中,我们给year属性赋的值是一个字符串型而不是数字型,这时TypeScript会提示错误。

(3). 提供默认属性值

除了类型检查外,我们还可以用可选属性来提供默认属性值。在某些场景下,如果对象的某些属性没有被定义,那么我们可以提供一个默认值,以确保代码可以正常运行。

举个例子,在定义一个Product接口时可以使用可选属性提供一个price属性的默认值,如下所示:

interface Product {
  name: string;
  price?: number;
}

const shirt: Product = { name: 'Shirt' };
const pants: Product = { name: 'Pants', price: 45.00 };

console.log(shirt.price || 15.00); // 15
console.log(pants.price || 15.00); // 45

在上面的例子中,我们给shirt对象定义了一个默认的price属性值为15,在打印price属性时,因为shirt对象没有定义price属性,所以输出的值是默认值15。而在打印pantsprice属性时,因为pants对象定义了price属性,输出的是45,这是由于该属性已定义的值是45。

2. 只读属性

TypeScript中,我们可以声明一个对象类型中的属性为只读属性,即该属性的值一旦被赋值就不能再被修改。

举例来说,假设有一个Student类型的对象,其中包含学生的姓名和年龄。我们可以将学生的姓名声明为只读属性,代码如下:

type Student = {
  readonly name: string;
  age: number;
}

在上述代码中,我们使用了readonly关键字来将name属性声明为只读属性。这意味着一旦我们给该属性赋值,就无法再修改它的值。

下面再举一个例子,假设我们有一个Point类型的对象,包含了二维平面上的坐标x和y。我们可以将该对象中的x和y属性都声明为只读属性,以保证对象的坐标值不会被意外修改。代码如下:

type Point = {
  readonly x: number;
  readonly y: number;
}

const p: Point = { x: 0, y: 0 };

// 错误,无法修改只读属性
p.x = 10;

在上述代码中,我们使用了readonly关键字将Point类型中的x和y属性都声明为只读属性。在给p对象中的x属性赋值之后,我们试图修改该属性的值,但是因为它是只读属性,所以会编译错误。

3. 索引签名

在 TypeScript 中,对象类型可以包含索引签名,以支持在动态属性上访问属性值。索引签名允许您在对象类型中定义一个模式,该模式指定应该具有哪些属性和属性类型。以下是一个示例:

interface ExampleObject {
  [key: string]: string;
}

const exampleObject: ExampleObject = {
  property1: "value1",
  property2: "value2",
  // ...
};

这里的索引签名 [key: string]: string 意味着对象 ExampleObject 中的所有属性的键都是字符串,所有属性的值都是字符串。因此,可以使用类似于 exampleObject.property1 这样的关键字为其属性赋值或访问属性值。

下面是一些其他角度的示例:

  1. 在对象类型中使用数字索引签名,以表示索引为数字的属性:
interface ExampleObject {
  [key: number]: string;
}

const exampleObject: ExampleObject = {
  0: "value1",
  1: "value2",
  // ...
};
  1. 在对象类型中使用只读索引签名,以表示不希望在运行时更改的属性:
interface ExampleObject {
  readonly [key: string]: string;
}

const exampleObject: ExampleObject = {
  property1: "value1",
  property2: "value2",
  // ...
};

exampleObject.property1 = "new value"; // This will cause a TypeScript error
  1. 在对象类型中使用联合类型索引签名,以表示可以具有多个类型的属性:
interface ExampleObject {
  [key: string]: string | number;
}

const exampleObject: ExampleObject = {
  property1: "value1",
  property2: 2,
  // ...
};

在这个示例中,属性的值可以是字符串或数字。

4. 扩展类型

TypeScript中的对象类型是通过接口来定义的,接口可以扩展其他接口,从而实现对象类型的扩展。

例如,我们可以定义一个基础的对象类型接口Person,然后定义一个Student接口来继承Person接口并添加一些额外的属性:

interface Person {
  name: string;
  age: number;
}

interface Student extends Person {
  school: string;
  grade: string;
}

这样,Student接口就包含了Person接口中所有的属性,同时添加了school和grade属性。

5. 交叉类型

交叉类型(Intersection Types)是Typescript中的一种类型操作符,用于将多个类型合并成一个类型。它的语法是将多个类型通过 & 连接起来,例如:

type Person = {
  name: string;
  age: number;
};
type Employee = {
  employer: string;
  salary: number;
};

type Worker = Person & Employee;

在上面的例子中,我们定义了两个类型Person和Employee,并将它们通过 & 连接起来得到了一个新的类型Worker。这个新类型包含了两个原类型中的所有属性。

与交叉类型类似的还有联合类型(Union Types),用于将多个类型中的一个合并成一个类型,并采用 | 连接。

交叉类型和interface的extends扩展类型的区别

与交叉类型相比,使用interface的extends扩展类型可以实现类似的效果,但是它们的设计思想不同。extends用于在一个类型基础上扩展属性和方法,而交叉类型则是将多个类型合并起来以创建一个新的类型

例如,我们定义了一个接口Animal:

interface Animal {
  name: string;
  eat(): void;
}

然后定义了两个接口Dog和Person,并通过extends方式扩展了它们的属性和方法:

interface Dog extends Animal {
  bark(): void;
}

interface Person extends Animal {
  age: number;
  speak(): void;
}

上面代码中,Dog和Person都扩展了Animal接口,即它们都继承了Animal中的name属性和eat方法。与交叉类型不同的是,Dog和Person无法同时拥有Animal以外的属性和方法。

综上所述,交叉类型和extends扩展类型虽然都用于继承和合并类型,但是它们的应用场景和用途不同。交叉类型适合于将多个类型合并为一个类型,而extends扩展类型适合于在一个类型基础上扩展属性和方法。在不同的场景中,我们可以选择不同的方式来定义和组合类型。

6. 泛型对象类型

泛型对象类型可以用于对象属性中的类型声明。例如,以下代码定义了一个对象类型,该对象具有不同类型的属性:

interface List<T> {
  data: T[]
  add: (item: T) => void
}

const list1: List<string> = {
  data: ['hello', 'world'],
  add(item) {
    this.data.push(item)
  }
}

const list2: List<number> = {
  data: [1, 2],
  add(item) {
    this.data.push(item)
  }
}

在上面的代码中,<T>表示泛型对象类型,我们在List<T>中使用了该类型,以声明data属性和add方法的参数和返回类型。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TypeScript中的对象类型(可选属性 只读属性 交叉类型) 的相关文章

随机推荐

  • (五)unity shader基础之——————学习shader所需的数学基础:下篇(坐标空间:模型空间、世界空间、观察空间、裁剪空间、屏幕空间、法线变换等)

    一 坐标空间 上篇文章讲述了如何使用矩阵来表示基本的变换 如平移 旋转和缩放 在本节我们将关注如何使用这些变换来对坐标空间进行变换 渲染游戏的过程可以理解成是把一个个顶点经过层层处理最终转换为屏幕上的过程 本节我们就将学习这个转换过程是如何
  • Python类和对象编写一个小游戏【含注释】

    定义一个鱼类和龟类并编写游戏 假设游戏场景为范围 x y 为0 lt x lt 10 0 lt y lt 10 游戏生成1只乌龟和10条鱼 它们的移动方向均随机 乌龟的最大移动能力是2 Ta可以随机选择1还是2移动 鱼儿的最大移动能力是1
  • 集合--10万随机数问题

    1 求十万个数据每个数据出现的次数 import java util ArrayList import java util Random import java util HashMap import java util Iterator
  • torch.optim.SGD()

    其中的SGD就是optim中的一个算法 优化器 随机梯度下降算法 PyTorch 的优化器基本都继承于 class Optimizer 这是所有 optimizer 的 base class torch optim是一个实现了各种优化算法的
  • QT之Excel表格操作

    QT之Excel表格操作 提前准备 打开读取excel文件 写入保存excel文件 提前准备 pro文件中添加 QT axcontainer 在需要使用excel的文件中添加 include
  • GitLab 仓库管理 创建一个仓库详细步骤

    Gitlab 仓库管理 GitLab 是通过组 group 的概念来统一管理仓库 project 和用户 user 通过创建组 在组下再创建仓库 再将用户加入到组 从而实现用户与仓库的权限管理 创建仓库之前先创建组 创建组 New grou
  • 状态空间模型

    一 状态空间模型简述 状态空间模型是动态时域模型 以隐含着的时间为自变量 状态空间模型包括两个模型 一是状态方程模型 反映动态系统在输入变量作用下在某时刻所转移到的状态 二是输出或量测方程模型 它将系统在某时刻的输出和系统的状态及输入变量联
  • html文字下排输入,HTML input text单行文本输入框简介说明

    摘要 下文讲述html代码中input type text 时的相关属性简介说明 如下所示 input type text 简介 当 input标签中 type text 时 代表此标签是一个单行文本输入框 单行文本框还包括一些属性 如下
  • 新项目需求调研

    从三个方面帮你建立起了对这个项目基本认识 概念层面 何谓访客管理系统 产品层面 访客管理系统通常有啥功能 客户层面 什么样的目标客户会产生这种需求 需求调研四个维度 那么 了解了这些基本信息后 我们就可以开展需求调研了吗 显然是不够的 对于
  • 三菱fx2n64mr说明书_三菱PLC模块FX3U-64MR/DS使用手册

    三菱PLC模块FX3U 64MR DS使用手册 FX1N 24MR 001 是三菱PLC FX1N系列 是一种卡片大小的PLC 适合在小型环境中进行控制 它具有的性能 串行通讯功能以及紧凑的尺寸 这使得它们能用在以前常规PLC无法安装的地方
  • 代码随想录--哈希--四数相加II

    给定四个包含整数的数组列表 A B C D 计算有多少个元组 i j k l 使得 A i B j C k D l 0 为了使问题简单化 所有的 A B C D 具有相同的长度 N 且 0 N 500 所有整数的范围在 2 28 到 2 2
  • 用DOS命令合并多个文本文件

    作者 iamlaosong 从总部系统下的干线数据 有30个文本文件 希望变成一个Excel文件 方法是先用copy命令将文本合成一个 再用excel打开 最后保存为Excel文件 步骤如下 1 将所有的文本文档拷贝到同一个文件夹 然后单击
  • 半透明信息显示浮动窗口的实现

    实现目的 在一些画图软件中 经常需要向用户展示鼠标移动到的位置的对象的一些参数信息 此时 完成一个交互性友好的信息显示界面就相当的重要了 因为一个软件的好坏 在用户的眼中 第一感觉甚至是第一重要的就是视觉效果和可操作性 当然 软件本身的稳定
  • 阿里云轻量应用服务器防火墙配置(全网最简单)

    阿里云轻量应用服务器防火墙配置 1 命令行配置 1 开启防火墙 systemctl start firewalld 2 限制端口 firewall cmd zone public add port 5672 tcp permanent 开放
  • 过拟合:所表现的就是模型训练误差很小,但测试误差很大,对于产生这种现象以下说法正确

    过拟合 所表现的就是模型训练误差很小 但测试误差很大 对于产生这种现象以下说法正确 提示 基础知识 1 深度学习机器学习笔试面试知识 正则化 文章目录 过拟合 所表现的就是模型训练误差很小 但测试误差很大 对于产生这种现象以下说法正确 TO
  • 关于echarts 图,在切换tab后,返回时宽度变窄的问题

    项目场景 提示 这里简述项目相关背景 最近在做一个统计报表的项目 需要插入ECharts 图表和表格做统计 并且可以导出Excel 表格 问题描述 提示 这里描述项目中遇到的问题 在开发过程中 碰到了一个 echarts 图在切换到 tab
  • KubeEdge环境搭建(支持网络插件flannel)

    KubeEdge环境搭建 准备工作 K8s集群环境搭建 准备开始 配置国内镜像 仅amd64架构 如果是arm架构的不要更改镜像 安装docker 安装K8s 初始化Master节点 网络插件安装 部署可视化KuBoard Cloud节点配
  • 算法的复杂度解析(时间复杂度和空间复杂度)

    时间复杂度与空间复杂度 1 算法的复杂度 2 时间复杂度 1 大O表示法 2 大O推导方法 3 一些常见的大O运行时间 3 空间复杂度 4 个别特殊举例 1 斐波那契数列的时间和空间复杂度 2 二分法的时间复杂度和空间复杂度 1 算法的复杂
  • 单片机C语言 -- 基于条件选择的状态机编程技巧

    感谢阅读本文 在接下来很长的一段时间里 我将陆续分享项目实战经验 从电源 单片机 晶体管 驱动电路 显示电路 有线通讯 无线通信 传感器 原理图设计 PCB设计 软件设计 上位机等 给新手综合学习的平台 给老司机交流的平台 所有文章来源于项
  • TypeScript中的对象类型(可选属性 只读属性 交叉类型)

    一 定义对象类型 在TypeScript中定义对象类型有以下三种方式 1 匿名对象类型 匿名对象类型是在定义变量时直接使用花括号 来定义一个对象类型 例如 const person name string age number name J