广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >详解TS对象扩展运算符和rest运算符
  • 530
分享到

详解TS对象扩展运算符和rest运算符

2024-04-02 19:04:59 530人浏览 薄情痞子
摘要

目录概述对象 rest 属性对象扩展属性制作对象的浅拷贝keyof 和查找类型keyof 操作符号索引类型查询概述 typescript 2.1 增加了对 对象扩展运算和 rest

概述

typescript 2.1 增加了对 对象扩展运算和 rest 属性提案的支持,该提案在 ES2018 中标准化。可以以类型安全的方式使用 rest 和 spread 属性。

对象 rest 属性

假设已经定义了一个具有三个属性的简单字面量对象


const marius = {
  name: "Marius Schulz",
  WEBsite: "https://mariusschulz.com/",
  twitterHandle: "@mariusschulz"
};

使用 es6 解构语法,可以创建几个局部变量来保存相应属性的值。TypeScript 将正确地推断每个变量的类型:


const { name, website, twitterHandle } = marius;

name;          // Type string
website;       // Type string
twitterHandle; // Type string

这些都是正确的,但这到现在也啥新鲜的。除了提取感兴趣的一组属性之外,还可以使用...语法将所有剩余的属性收集到rest元素中:


const { twitterHandle, ...rest } = marius;

twitterHandle; // Type string
rest; // Type { name: string; website: string; }

TypeScript 会为得到结果的局部变量确定正确的类型。虽然twitterHandle变量是一个普通的字符串,但rest变量是一个对象,其中包含剩余两个未被解构的属性。

对象扩展属性

假设咱们希望使用fetch()api 发出 Http 请求。它接受两个参数:一个URL和一个options对象,options包含请求的任何自定义设置。

在应用程序中,可以封装对fetch()的调用,并提供默认选项和覆盖给定请求的特定设置。这些配置项类似如下:


const defaultOptions = {
  method: "GET",
  credentials: "same-origin"
};

const requestOptions = {
  method: "POST",
  redirect: "follow"
};

使用对象扩展,可以将两个对象合并成一个新对象,然后传递给fetch()方法


// Type { method: string; redirect: string; credentials: string; }
const options = {
  ...defaultOptions,
  ...requestOptions
};

对象扩展属性创建一个新对象,复制defaultOptions中的所有属性值,然后按照从左到右的顺序复制requestOptions中的所有属性值,最后得到的结果如下:


console.log(options);
// {
//   method: "POST",
//   credentials: "same-origin",
//   redirect: "follow"
// }

请注意,分配顺序很重要。如果一个属性同时出现在两个对象中,则后分配的会替换前面的。

当然,TypeScript 理解这种顺序。因此,如果多个扩展对象使用相同的键定义一个属性,那么结果对象中该属性的类型将是最后一次赋值的属性类型,因为它覆盖了先前赋值的属性:


const obj1 = { prop: 42 };
const obj2 = { prop: "Hello World" };

const result1 = { ...obj1, ...obj2 }; // Type { prop: string }
const result2 = { ...obj2, ...obj1 }; // Type { prop: number }

制作对象的浅拷贝

对象扩展可用于创建对象的浅拷贝。假设咱希望通过创建一个新对象并复制所有属性来从现有todo项创建一个新todo项,使用对象就可以轻松做到:


const todo = {
  text: "Water the flowers",
  completed: false,
  tags: ["garden"]
};

const shallowCopy = { ...todo };

实际上,你会得到一个新对象,所有的属性值都被复制:


console.log(todo === shallowCopy);
// false

console.log(shallowCopy);
// {
//   text: "Water the flowers",
//   completed: false,
//   tags: ["garden"]
// }

现在可以修改text属性,但不会修改原始的todo项:


hallowCopy.text = "Mow the lawn";

console.log(shallowCopy);
// {
//   text: "Mow the lawn",
//   completed: false,
//   tags: ["garden"]
// }

console.log(todo);
// {
//   text: "Water the flowers",
//   completed: false,
//   tags: ["garden"]
// }

但是,新的todo项引用与第一个相同的tags数组。由于是浅拷贝,改变数组将影响这两个todo


shallowCopy.tags.push("weekend");

console.log(shallowCopy);
// {
//   text: "Mow the lawn",
//   completed: false,
//   tags: ["garden", "weekend"]
// }

console.log(todo);
// {
//   text: "Water the flowers",
//   completed: false,
//   tags: ["garden", "weekend"]
// }

如果想创建一个序列化对象的深拷贝,可以考虑使用JSON.parse(jsON.stringify(obj))或其他方法,如object.assign()。对象扩展仅拷贝属性值,如果一个值是对另一个对象的引用,则可能导致意外的行为。

keyof 和查找类型

JS 是一种高度动态的语言。在静态类型系统中捕获某些操作的语义有时会很棘手。以一个简单的prop函数为例:


function prop(obj, key) {
  return obj[key];
}

它接受一个对象和一个键,并返回相应属性的值。一个对象的不同属性可以有完全不同的类型,咱们甚至不知道obj是什么样子的。

那么如何在 TypeScript 中编写这个函数呢?先尝试一下:

有了这两个类型注释,obj必须是对象,key必须是字符串。咱们现在已经限制了两个参数的可能值集。然而,TS 仍然推断返回类型为any:


const todo = {
  id: 1,
  text: "Buy milk",
  due: new Date(2016, 11, 31)
};

const id = prop(todo, "id");     // any
const text = prop(todo, "text"); // any
const due = prop(todo, "due");   // any

如果没有更进一步的信息,TypeScript 就不知道将为key参数传递哪个值,所以它不能推断出prop函数的更具体的返回类型。咱们需要提供更多的类型信息来实现这一点。

keyof 操作符号

在 JS 中属性名称作为参数的 API 是相当普遍的,但是到目前为止还没有表达在那些 API 中出现的类型关系。

TypeScript 2.1 新增加keyof操作符。输入索引类型查询或keyof,索引类型查询keyof T产生的类型是T的属性名称。假设咱们已经定义了以下Todo接口:


interface Todo {
  id: number;
  text: string;
  due: Date;
}

各位可以将keyof操作符应用于Todo类型,以获得其所有属性键的类型,该类型是字符串字面量类型的联合


type TodoKeys = keyof Todo; // "id" | "text" | "due"

当然,各位也可以手动写出联合类型"id" | "text" | "due",而不是使用keyof,但是这样做很麻烦,容易出错,而且维护起来很麻烦。而且,它应该是特定于Todo类型的解决方案,而不是通用的解决方案。

索引类型查询

有了keyof,咱们现在可以改进prop函数的类型注解。我们不再希望接受任意字符串作为key参数。相反,咱们要求参数key实际存在于传入的对象的类型上


function prop <T, K extends keyof T>(obj: T, key: K) {
  return obj[key]
}

TypeScript 现在以推断prop函数的返回类型为T[K],这个就是所谓的索引类型查询或查找类型。它表示类型T的属性K的类型。如果现在通过prop方法访问下面todo的三个属性,那么每个属性都有正确的类型:


const todo = {
  id: 1,
  text: "Buy milk",
  due: new Date(2016, 11, 31)
};

const id = prop(todo, "id");     // number
const text = prop(todo, "text"); // string
const due = prop(todo, "due");   // Date

现在,如果传递一个todo对象上不存在的键会发生什么

编译器会报错,这很好,它阻止咱们试图读取一个不存在的属性。

另一个真实的示例,请查看与TypeScript编译器一起发布的lib.es2017.object.d.ts类型声明文件中Object.entries()方法:


interface ObjectConstructor {
  // ...
  entries<T extends { [key: string]: any }, K extends keyof T>(o: T): [keyof T, T[K]][];
  // ...
}

entries方法返回一个元组数组,每个元组包含一个属性键和相应的值。不可否认,在返回类型中有大量的方括号,但是我们一直在寻找类型安全性。

以上就是详解TS对象扩展运算符和rest运算符的详细内容,更多关于TS对象扩展运算符和rest运算符的资料请关注编程网其它相关文章!

--结束END--

本文标题: 详解TS对象扩展运算符和rest运算符

本文链接: https://www.lsjlt.com/news/125226.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 详解TS对象扩展运算符和rest运算符
    目录概述对象 rest 属性对象扩展属性制作对象的浅拷贝keyof 和查找类型keyof 操作符号索引类型查询概述 TypeScript 2.1 增加了对 对象扩展运算和 rest ...
    99+
    2022-11-12
  • es6对象扩展运算符怎么应用
    ES6的对象扩展运算符(`...`)可以用于复制对象、合并对象、传递函数参数等多种应用。 复制对象:使用对象扩展运算符可以非常方...
    99+
    2023-10-25
    es6
  • JavaScript展开运算符和剩余运算符的区别详解
    目录什么是剩余运算符?剩余运算符在JavaScript函数中是如何工作的?注意!不能在包含剩余参数的函数体中使用"use strict"剩余运算符在参数解构中是如...
    99+
    2022-11-12
  • JavaScript中如何使用扩展运算符展开对象
    这篇文章主要为大家展示了“JavaScript中如何使用扩展运算符展开对象”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JavaScript中如何使用扩展运算符展开对象”这篇文章吧。展开对象co...
    99+
    2023-06-04
  • JavaScript中运算符与数组扩展详细讲解
    目录运算符扩展运算符指数运算符链判断运算符Null判断运算符逻辑赋值运算符数组扩展方法Array.from()Array.of()copyWithin()find()fill()fl...
    99+
    2022-11-13
    JS运算符与数组扩展 JS数组扩展 JS运算符
  • C++类与对象之运算符重载详解
    目录运算符重载加号运算符重载左移运算符重载递增运算符重载递减运算符重载赋值运算符重载关系运算符重载函数调用运算符重载总结运算符重载 运算符重载概念:对已有的运算符重新进行定义,赋予其...
    99+
    2022-11-12
  • 怎么理解python运算对象、运算符、表达式和语句
    本篇内容主要讲解“怎么理解python运算对象、运算符、表达式和语句”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解python运算对象、运算符、表达式和语句”吧!编程的本质就是数据和运算...
    99+
    2023-06-02
  • ES6箭头函数、rest参数、扩展运算符和Symbol如何使用
    今天小编给大家分享一下ES6箭头函数、rest参数、扩展运算符和Symbol如何使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文...
    99+
    2022-10-19
  • Python海象运算符超详细讲解
    目录介绍语法用法if 语句while 循环while 循环逐行读取文件while 循环验证输入推导式三元表达式总结介绍 海象运算符,即 := ,在 PEP 572 中被提出,并在 P...
    99+
    2023-01-30
    Python海象运算符 Python海象运算符作用
  • 运算符、表达式和内置对象
    一、实验目的 1.会使用IDLE编辑器编写简单数据类型; 2.掌握常量、变量的表示方式和简单操作; 3.掌握Python语言中基本的输入和输出方法; 4.掌握Python语言的各种运算符以及这些运算符...
    99+
    2023-10-07
    python 爬虫 numpy
  • python注释和运算符详解
    目录1.多文件项目演练2.注释(解释器不会解释#右侧内容)2.1单行注释(行注释) 2.2多行注释(块注释)3.算术运算符3.1运算符3.2优先级 总结 1.多文件项目演练 在day...
    99+
    2022-11-12
  • ES6扩展运算符的理解与使用场景
    目录1、替代apply方法,一般在函数调用时处理参数2、剩余参数(rest运算符),主要针对函数形参3、数据连接、合并4、数组和对象的拷贝5、字符串转数组6、在函数调用时使用拓展运算...
    99+
    2022-11-12
  • JavaScript扩展运算符的学习及应用详情(ES6)
    目录学习应用函数参数数组合并解构赋值字符串转换转换数组前言: 扩展运算符是ES6新增的一种运算符,他可以帮助我们简化代码,简化操作,所以在开发中是非常常用的,下面我将从学习与应用两个...
    99+
    2022-11-13
    JavaScript扩展运算符应用 JavaScript扩展运算符
  • Python中运算符"=="和"is"的详解
    前言 在讲is和==这两种运算符区别之前,首先要知道Python中对象包含的三个基本要素,分别是:id(身份标识)、python type()(数据类型)和value(值)。is和==都是对对象进行比较判断...
    99+
    2022-06-04
    详解 运算符 Python
  • JavaScript类型、运算符、对象和方法怎么用
    这篇文章主要介绍“JavaScript类型、运算符、对象和方法怎么用”,在日常操作中,相信很多人在JavaScript类型、运算符、对象和方法怎么用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaScr...
    99+
    2023-06-27
  • C#表达式和运算符详细解析
    目录类型转换1、表达式1.2 运算符分类2、数学运算符3、赋值运算符4、关系运算符5、布尔运算符6、位运算符6.1 &按位与运算6.2 或|按位运算6.3 异或^按位运算符6...
    99+
    2022-11-13
  • 关于Python中的海象运算符使用方法详解
    海象运算符(walrus operator)是 Python 3.8 中引入的一种新的语法,其使用方法如下: variable := expression 其中,expression...
    99+
    2023-05-16
    Python运算符 Python海象运算符
  • C++类与对象深入之运算符重载与const及初始化列表详解
    目录一:运算符重载相等运算符重载赋值运算符重载小于运算符重载二:const成员const修饰类的成员函数三:cin、cout重载四:初始化列表构造函数赋初值初始化列表explicit...
    99+
    2022-11-13
  • vue第三方库中存在扩展运算符报错问题的解决方案
    目录vue第三方库中存在扩展运算符报错问题解决方案1、引入babel依赖2、在vue项目的src/.babelrc文件中(没有自己创建)下修改解决方法:vue第三方库中存在扩展运算符...
    99+
    2022-11-13
  • Python教程之成员和身份运算符的用法详解
    目录成员运算符in 运算符'not in' 运算符身份运算符'is' 运算符'is not' 运算符成员运算符 Python 提供了两...
    99+
    2022-11-11
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作