仅知道键和值的类型,如何定义 TS 对象类型?

更新日期: 2022-04-18 阅读: 1.8k 标签: 类型

在学习 TS 的过程中,你遇到过类似的错误么?

let user = {}
user.id = "TS001" // 类型“{}”上不存在属性“id”。
user.name = "阿宝哥" // 类型“{}”上不存在属性“name”。

除了 any “大招” 之外,你还知道几种解决方案?阅读完本文,你将会找到一些答案。

这是小王他的月薪是包含了基本工资和月度奖金,这是小郭他的月薪只包含合同工资。

const Wang = {
  baseSalary: 10000, // 基本工资
  monthlyBonus: 2000 // 月度奖金
};
const Guo = {
  contractSalary: 15000 // 合同工资
}

这里我们可以实现一个 calculateSalary 函数来计算他们的薪资,计算逻辑实现起来很简单。但问题来了,在 TS 中如何定义该函数参数的类型呢?

function calculateSalary(salaryObject: ???) {
  let total = 0;
  for (const name in salaryObject) {
    total += salaryObject[name];
  }
  return total;
}

给你 3 秒钟的时间思考一下。你想到答案了么?其中一种方案是使用索引签名。当我们仅知道对象键和值的类型时,就可以使用索引签名来定义该对象的类型。

这是索引签名的语法

{ [key: KeyType]: ValueType }

其中 Key 的类型,只能是 string,number,symbol 或模版字面量类型,而值的类型可以是任意类型。

interface Dictionary {
  [key: boolean]: string;
}

其中模版字面量类型是 TypeScript 4.1 版本引入的新类型,结合索引签名我们可以定义更强大的类型:

interface PropChangeHandler {
  [key: `${string}Changed`]: () => void;
}
let handlers: PropChangeHandler = {
  idChanged: () => {}, // Ok
  nameChanged: () => {}, // Ok
  ageChange: () => {} // Error
};

了解索引签名的语法之后,我们就可以轻松地定义出 salaryObject 参数的类型:

function calculateSalary(salaryObject: { [key: string]: number }) {
  let total = 0;
  for (const name in salaryObject) {
    total += salaryObject[name];
  }
  return total;
}

有些时候,在定义对象类型时,会含有一些已知和未知的键,这时我们可以结合索引签名来定义该对象的类型:

interface Options {
  [key: string]: string | number | boolean;
  timeout: number; // 已知的键
}
const options: Options = {
  timeout: 1000,
  errorMessage: 'The request timed out!',
  isSuccess: false
};

在使用索引签名时,你可能会遇到这些困惑:

interface NumbersNames {
  [key: string]: string
}
const names: NumbersNames = {
  '1': 'one',
  '2': 'two',
  '3': 'three'
};
const value1 = names['1'] // Ok
const value2 = names[1] // Ok

type N0 = keyof NumbersNames // string | number
  • 为什么可以通过字符串 1 和数字 1 来访问对应的属性值。
  • 为什么 keyof NumbersNames 返回的 string 和 number 类型组成的联合类型。

这是因为当用作属性访问器中的键时,JavaScript 会隐式地将数字强制转换为字符串,TypeScript 也会执行这种转换。

除了使用索引签名之外,我们还可以使用 TS 内置的工具类型 Record 类型来定义 calculateSalary 函数的参数类型:

type Record<K extends keyof any, T> = {
  [P in K]: T;
};
function calculateSalary(salaryObject: Record<string, number>) {
  let total = 0;
  for (const name in salaryObject) {
    total += salaryObject[name];
  }
  return total;
}

那么索引签名和 Record 工具类型有什么区别呢?在一些场合下,它们都能定义出期望的类型。

const user1: Record<string, string> = { name: "阿宝哥" }; // Ok
const user2: { [key: string]: string } = { name: "阿宝哥" }; // Ok

对于索引签名来说,其键的类型,只能是 string,number,symbol 或模版字面量类型。而 Record 工具类型,键的类型可以是字面量类型或字面量类型组成的联合类型:

type User1 = {
  [key: "id"]: string; // Error
};
type User2 = {
  [key: "id" | "name"]: string; // Error
};
type User3 = Record<"id", string>; // Ok
type User4 = Record<"id" | "name", string>; // Ok
const user: User4 = {
  id: "TS001",
  name: "阿宝哥",
};

看完以上内容,你学会索引签名和 Record 工具类型了么?

来源: 全栈修仙之路


本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/11353

相关推荐

Js如何将String转化为Int

字符串到整型的一个转换,在面试过程中或者在工作中都会频繁遇到,那么string到js怎么转换呢 ?parseInt方法在format\'00\'开头的数字时会当作2进制转10进制的方法进行转换

Typescript内置类型与自定义类型

大家用过 Typescript 都清楚,很多时候我们需要提前声明一个类型,再将类型赋予变量。例如在业务中,我们需要渲染一个表格,往往需要定义:

Js实现base64,file和blob相互转换

JavaScript实现base64,file和blob相互转换:base64转为Blob;Blob转为base64;base64转换为file;js图片转换为base64;在Java中base64和File相互转换

Js的6种基本数据类型

在JS中一共有六种数据类型 String:字符串 Number:数值 Boolean:布尔值 Null:空值 Undefined:未定义 Object:对象 ,其中String,Number,Boolean,Null,Undefined属于基本数据类型而Object属于引用数据类型

JavaScript判断字符串是否为数字类型

JavaScript中有Number.isInteger可以判断一个字符串是否为整数。不过目前JS没有内置的函数来判断一个数字是否为包含小数的数字:

TypeScript never 类型

在类型理论(数学逻辑中的一种理论)中, 底部类型 是没有值的类型。也称为零或空类型,有时用 falsum(⊥)表示。 数学理论与计算机的发展是相辅相成的,底部类型在计算机科学中也有一定的应用场景。

JS数据类型转换表

下表显示了将不同的JavaScript值转换为Number,String和Boolean的结果:注意:引号(\\\"\\\")中的值表示字符串值。在红色的值是程序员可能不希望被转换为的值。

Js的typeof返回哪些数据类型?

JavaScript中的数据类型:值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。引用数据类型:对象(Object)、数组(Array)、函数(Function)。

为你的 JavaScript 项目添加智能提示和类型检查

近在做项目代码重构,其中有一个要求是为代码添加智能提示和类型检查。智能提示,英文为 IntelliSense,能为开发者提供代码智能补全、悬浮提示、跳转定义等功能,帮助其正确并且快速完成编码。

JS中的布尔 数字 字符串

JS中所有的值都可以转换成布尔类型 使用Boolean()或者 !!(两个感叹号),JS中所有的值都可以转换成数字类型,使用Number()或+。数字类型转换场景目的只有一个,用于计算,将后台传递的数据,从字符串转换为数字并参与计算

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!