如何在TypeScript中定义未知结构的对象类型?

发布时间:2023年12月31日

图片

一个大多数人在学习TypeScript时都会遇到的问题,你能想到多少解决方案呢?

你在学习TypeScript时遇到过类似的错误吗?

图片

要解决这个错误,一个非常暴力的方法是使用?any?类型:

let user: any = {}user.id = "TS001";user.name = "Bytefer";

除了使用?any?类型,你还知道多少种解决方案? 在本文中,我将介绍另外3种解决方案。在继续阅读之前,我建议你花点时间思考一下。

图片

一种解决方案是使用?type?或?interface?定义?User?类型:???????

interface User {  id: string;  name: string;}??????
let user = {} as User;user.id = "TS001";user.name = "Bytefer";

尽管使用?User?类型,前面的问题可以解决。但是,如果您为用户对象设置了一个新的?age?属性,将显示以下错误消息:

Property 'age' does not exist on type 'User'.ts(2339)

那么,如何解决动态属性分配问题呢? 现在,我们可以使用TypeScript的索引签名了。当我们只知道对象键和值的类型时,可以使用索引签名来定义该对象的类型。索引签名的语法如下:

图片

键的类型只能是字符串、数字、符号或模板文字类型,而值的类型可以是任何类型。

图片

模板文字类型是TypeScript 4.1中引入的一种新类型,结合索引签名,我们可以定义更强大的类型。

图片

一旦理解了索引签名的语法,就可以很容易地定义一个新的?User?类型:???????

interface User {  id: string;  name: string;  [key: string]: string;}

在id和name已经是属性的情况下,我们通过索引签名将?User?类型的其他属性的类型设置为字符串类型。在使用索引签名时,您可能会产生以下疑问:

图片

  • 为什么可以通过字符串“1”和数字1访问相应的属性值?

  • 为什么keyof NumbersNames返回字符串和数字类型的联合类型?
    ?

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

除了使用索引签名,我们还可以使用TypeScript内置的实用工具类型?Record?类型来定义?User?类型。?Record?实用程序类型的作用如下:

图片

type User = Record<string, string>
???????
let user = {} as User;user.id = "TS001"; // Okuser.name = "Bytefer"; // Ok

那么索引签名和Record实用程序类型之间的区别是什么呢? 在某些情况下,它们都定义了期望的类型。???????

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

对于索引签名,键类型只能是字符串、数字、符号或模板文字类型。对于Record实用程序类型,键类型可以是文字类型或文字类型的联合:

图片

为了更好地理解?Record?实用程序类型,让我们看一下它的内部实现:???????

/** * Construct a type with a set of properties K of type T. * typescript/lib/lib.es5.d.ts */type Record<K extends keyof any, T> = {    [P in K]: T;};

Record?实用程序类型在内部使用TypeScript映射的类型,它在其他内置实用程序类型中也被广泛使用。

读完这篇文章,我相信你已经理解了TypeScript索引类型和Record??Record?工具类型。

欢迎关注公众号:文本魔术,了解更多

文章来源:https://blog.csdn.net/wannianchuan/article/details/135312973
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。