纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

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

浅笑·   2021-05-06 我要评论
想了解详解TS对象扩展运算符和rest运算符的相关内容吗浅笑·在本文为您仔细讲解TS对象扩展运算符和rest运算符的相关知识和一些Code实例欢迎阅读和指正我们先划重点:TS,对象扩展,TS,rest,TS,运算符下面大家一起来学习吧

概述

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方法返回一个元组数组每个元组包含一个属性键和相应的值不可否认在返回类型中有大量的方括号但是我们一直在寻找类型安全性


相关文章

猜您喜欢

  • Goland Go Modules创建管理项目 Goland使用Go Modules创建/管理项目的操作

    想了解Goland使用Go Modules创建/管理项目的操作的相关内容吗deantzzz在本文为您仔细讲解Goland Go Modules创建管理项目的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Goland,Go,Modules,创建管理项目下面大家一起来学习吧..
  • Mybatis动态SQL IF语句 Mybatis动态SQL之IF语句详解

    想了解Mybatis动态SQL之IF语句详解的相关内容吗TheLightOfCode在本文为您仔细讲解Mybatis动态SQL IF语句的相关知识和一些Code实例欢迎阅读和指正我们先划重点:mybatis动态sql语句,mysql动态sql语句基本语法,mybatis执行动态sql下面大家一起来学习吧..

网友评论

Copyright 2020 www.fresh-weather.com 【世纪下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式