TypeScript对象类型


版权声明


TypeScript对象类型概述

对象用于保存一组相关数据,例如一个用户、一个学生、一个商品或一条订单记录。与单个字符串、数字、布尔值不同,对象通常由多个属性组成,每个属性都表示这组数据中的一个具体字段。在 JavaScript 中,对象的属性添加和修改比较自由,但这种自由也可能带来问题。例如,一个商品对象中的价格本来应该是数字,如果后续被错误地改成字符串,就可能影响计算、排序或页面展示。

TypeScript 的对象类型可以明确规定对象应该包含哪些属性,以及每个属性应该保存什么类型的数据。对象类型通常写在变量名后面,用一对花括号描述对象结构,例如 { username: string; age: number }。这表示对象必须包含 usernameage 两个属性,其中 username 必须是字符串,age 必须是数字。对象数据本身则写在等号右边,例如 { username: "jack", age: 18 }。初学时要注意区分:等号左边描述类型结构,等号右边才是实际数据。

使用对象类型时,属性名和属性类型都要对应。对象类型中声明了什么属性,对象数据中就应该按照对应名称提供属性。如果类型中要求的是 name,实际对象却写成 username,TypeScript 会认为对象结构不匹配。同样,如果类型中规定 pricenumber,实际数据却写成 "199",也会出现类型错误。带引号的 "199" 是字符串,不是数字。

对象类型还会检查属性是否完整。如果某个属性在类型中被定义为普通属性,那么对象数据中通常必须提供这个属性。缺少必需属性会导致类型错误。相反,如果直接给一个带有对象类型标注的变量赋值,对象中多出类型里没有声明的属性,也可能出现错误。对于初学者来说,可以先理解为:对象类型中声明了哪些属性,对象数据就按照这个结构来写,既不要少写必需属性,也不要随意增加未声明属性。

有些对象属性并不是每次都一定存在,这时可以使用可选属性。可选属性的写法是在属性名后面加 ?,例如 address?: string。它表示对象可以没有 address 属性;如果提供了 address,它的值必须是字符串。可选属性适合描述接口数据、用户资料、商品描述等不一定完整的数据字段。需要注意的是,可选属性如果没有提供,读取时可能得到 undefined,后续使用时要考虑这种情况。

对象类型也可以和数组结合使用,形成对象数组。对象数组用于保存一组结构相同的对象,例如学生列表、商品列表、用户列表等。写法通常类似 { name: string; age: number }[],表示数组中的每一项都必须是具有 nameage 属性的对象。对象数组在 Vue3 中非常常见,后续学习列表渲染、表格展示和接口返回数据时,经常会处理这类结构。

对象类型还经常用于函数参数。当一个函数接收一个对象作为参数时,可以直接为这个参数标注对象类型,明确调用函数时必须传入怎样的对象。例如,打印用户信息的函数可以要求参数必须包含 usernameage。这样一来,如果调用函数时缺少属性,或者属性类型不正确,TypeScript 就能提前提示问题。

如果对象属性较少,可以直接在变量或函数参数中写对象类型。但当对象结构变复杂,或者同一种对象结构需要多次使用时,直接书写对象类型就会显得冗长。后续学习类型别名和接口后,可以把对象结构单独提取出来,让代码更清晰。掌握对象类型后,再学习 Vue3 中的数据对象、列表数据、组件参数和接口返回结果时,会更容易理解这些数据结构的含义。

案例源码

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>TypeScript 对象类型</title>
</head>
<body>
  <h1>TypeScript 对象类型</h1>

  <p>
    本节学习 TypeScript 中对象类型的基本写法。
    对象用于保存一组相关数据,例如一个学生、一个用户、一个商品等。
  </p>

  <p>
    在 JavaScript 中,对象的属性可以比较自由地添加和修改。
    在 TypeScript 中,可以明确规定对象应该有哪些属性,
    以及每个属性应该保存什么类型的数据。
  </p>

  <p>
    说明:本节中的代码是 TypeScript 代码,浏览器不能直接运行。
    当前阶段建议使用 TypeScript 官方在线工具
    <a href="https://www.typescriptlang.org/play/" target="_blank">TypeScript Playground</a>
    测试代码。
  </p>

  <hr>

  <h2>一、为什么需要对象类型</h2>

  <p>
    在 JavaScript 中,对象常用于保存一组相关数据。
  </p>

  <pre><code>let student = {
  name: "张三",
  age: 18
};</code></pre>

  <p>
    这个对象表示一个学生。
    其中,<code>name</code> 表示姓名,<code>age</code> 表示年龄。
  </p>

  <p>
    如果后续代码中不小心把年龄改成字符串,JavaScript 本身不会在编写阶段提示错误。
  </p>

  <pre><code>student.age = "十八";</code></pre>

  <p>
    这可能导致后续代码出现问题。
    例如,原本想对年龄进行数字运算,但年龄却变成了字符串。
  </p>

  <p>
    TypeScript 可以通过对象类型规定对象属性的类型。
  </p>

  <pre><code>let student: { name: string; age: number } = {
  name: "张三",
  age: 18
};

student.age = 20;     // 正确
student.age = "二十"; // 错误:age 应该是 number</code></pre>

  <p>
    这就是对象类型的作用:
    <strong>规定对象应该有哪些属性,并规定每个属性的数据类型。</strong>
  </p>

  <hr>

  <h2>二、对象类型的基本写法</h2>

  <p>
    对象类型的基本格式如下:
  </p>

  <pre><code>let 变量名: { 属性名: 类型; 属性名: 类型 } = {
  属性名: 值,
  属性名: 值
};</code></pre>

  <p>
    例如:
  </p>

  <pre><code>let user: { username: string; age: number } = {
  username: "jack",
  age: 18
};</code></pre>

  <p>
    这段代码中:
  </p>

  <ol>
    <li><code>user</code> 是变量名。</li>
    <li><code>{ username: string; age: number }</code> 是对象类型。</li>
    <li><code>username: string</code> 表示对象必须有 <code>username</code> 属性,并且值必须是字符串。</li>
    <li><code>age: number</code> 表示对象必须有 <code>age</code> 属性,并且值必须是数字。</li>
  </ol>

  <p>
    注意:
    等号左边的 <code>username: string</code> 是类型标注;
    等号右边的 <code>username: "jack"</code> 才是真正的数据。
  </p>

  <pre><code>let user: { username: string; age: number } = {
  username: "jack",
  age: 18
};</code></pre>

  <p>
    可以这样理解:
  </p>

  <pre><code>{ username: string; age: number }  // 规定对象结构
{ username: "jack", age: 18 }      // 提供对象数据</code></pre>

  <hr>

  <h2>三、对象属性名必须对应</h2>

  <p>
    初学者容易疑惑:
    对象类型中的属性名是不是可以随便写?
  </p>

  <p>
    答案是:
    <strong>不能随便写。</strong>
    对象类型中的属性名,必须和对象数据中的属性名对应。
  </p>

  <pre><code>let student: { name: string; age: number } = {
  name: "张三",
  age: 18
};</code></pre>

  <p>
    上面代码是正确的,因为类型中声明了 <code>name</code> 和 <code>age</code>,
    对象数据中也提供了 <code>name</code> 和 <code>age</code>。
  </p>

  <p>
    下面这种写法是错误的:
  </p>

  <pre><code>let student: { name: string; age: number } = {
  username: "张三",
  age: 18
};</code></pre>

  <p>
    错误原因:
    类型中要求对象必须有 <code>name</code> 属性,
    但是实际对象中写的是 <code>username</code> 属性。
  </p>

  <p>
    如果想使用 <code>username</code> 作为属性名,
    类型中也应该写成 <code>username</code>。
  </p>

  <pre><code>let student: { username: string; age: number } = {
  username: "张三",
  age: 18
};</code></pre>

  <p>
    也就是说:
    <strong>类型中的属性名,要和对象中的属性名保持一致。</strong>
  </p>

  <hr>

  <h2>四、对象属性类型必须对应</h2>

  <p>
    除了属性名要对应,属性值的类型也要对应。
  </p>

  <pre><code>let product: { name: string; price: number } = {
  name: "键盘",
  price: 199
};</code></pre>

  <p>
    上面代码中:
  </p>

  <ol>
    <li><code>name</code> 应该是字符串。</li>
    <li><code>price</code> 应该是数字。</li>
  </ol>

  <p>
    所以下面这种写法是错误的:
  </p>

  <pre><code>let product: { name: string; price: number } = {
  name: "键盘",
  price: "199"
};</code></pre>

  <p>
    错误原因:
    <code>price</code> 被标注为 <code>number</code>,
    但是 <code>"199"</code> 是字符串。
  </p>

  <p>
    正确写法:
  </p>

  <pre><code>let product: { name: string; price: number } = {
  name: "键盘",
  price: 199
};</code></pre>

  <p>
    记住:
    <strong>属性名要对,属性值的类型也要对。</strong>
  </p>

  <hr>

  <h2>五、对象缺少属性会报错</h2>

  <p>
    如果对象类型中规定了某个属性,
    那么对象数据中通常必须提供这个属性。
  </p>

  <pre><code>let user: { username: string; age: number } = {
  username: "jack",
  age: 18
};</code></pre>

  <p>
    上面代码是正确的,因为对象同时提供了 <code>username</code> 和 <code>age</code>。
  </p>

  <p>
    下面这种写法是错误的:
  </p>

  <pre><code>let user: { username: string; age: number } = {
  username: "jack"
};</code></pre>

  <p>
    错误原因:
    类型中要求对象必须有 <code>age</code> 属性,
    但是实际对象中缺少了 <code>age</code>。
  </p>

  <p>
    正确写法:
  </p>

  <pre><code>let user: { username: string; age: number } = {
  username: "jack",
  age: 18
};</code></pre>

  <hr>

  <h2>六、对象多出属性也可能报错</h2>

  <p>
    如果直接给一个带类型标注的对象变量赋值,
    对象中多写了类型中没有声明的属性,也可能报错。
  </p>

  <pre><code>let user: { username: string; age: number } = {
  username: "jack",
  age: 18,
  address: "北京"
};</code></pre>

  <p>
    错误原因:
    类型中只声明了 <code>username</code> 和 <code>age</code>,
    但是对象数据中多出了 <code>address</code>。
  </p>

  <p>
    如果确实需要 <code>address</code> 属性,
    就应该在类型中声明它。
  </p>

  <pre><code>let user: { username: string; age: number; address: string } = {
  username: "jack",
  age: 18,
  address: "北京"
};</code></pre>

  <p>
    当前阶段可以先记住:
    <strong>对象类型中声明了哪些属性,对象数据就按照这个结构来写。</strong>
  </p>

  <hr>

  <h2>七、可选属性</h2>

  <p>
    有些属性不是必须存在的。
    这种属性可以定义为可选属性。
  </p>

  <p>
    可选属性的写法是在属性名后面加 <code>?</code>。
  </p>

  <pre><code>let user: { username: string; age: number; address?: string } = {
  username: "jack",
  age: 18
};</code></pre>

  <p>
    这里的 <code>address?: string</code> 表示:
    <code>address</code> 属性可以有,也可以没有。
    如果有,必须是字符串。
  </p>

  <p>
    下面两种写法都正确:
  </p>

  <pre><code>let user1: { username: string; age: number; address?: string } = {
  username: "jack",
  age: 18
};

let user2: { username: string; age: number; address?: string } = {
  username: "lucy",
  age: 20,
  address: "上海"
};</code></pre>

  <p>
    但是,如果提供了 <code>address</code>,它的值仍然必须是字符串。
  </p>

  <pre><code>let user: { username: string; age: number; address?: string } = {
  username: "jack",
  age: 18,
  address: 100
};</code></pre>

  <p>
    上面代码是错误的。
    因为 <code>address</code> 如果存在,就应该是字符串。
  </p>

  <hr>

  <h2>八、对象数组</h2>

  <p>
    在前端开发中,经常会遇到对象数组。
    例如,一个学生列表就是由多个学生对象组成的数组。
  </p>

  <pre><code>let students: { name: string; age: number }[] = [
  { name: "张三", age: 18 },
  { name: "李四", age: 19 },
  { name: "王五", age: 20 }
];</code></pre>

  <p>
    这段代码中:
  </p>

  <ol>
    <li><code>{ name: string; age: number }</code> 表示单个学生对象的类型。</li>
    <li><code>[]</code> 表示这是一个数组。</li>
    <li><code>{ name: string; age: number }[]</code> 表示数组中的每一项都必须是这种学生对象。</li>
  </ol>

  <p>
    如果数组中某个对象的属性类型不正确,就会报错。
  </p>

  <pre><code>let students: { name: string; age: number }[] = [
  { name: "张三", age: 18 },
  { name: "李四", age: "19" }
];</code></pre>

  <p>
    错误原因:
    第二个学生对象中的 <code>age</code> 应该是数字,
    但是写成了字符串 <code>"19"</code>。
  </p>

  <p>
    对象数组在 Vue3 中非常常见。
    例如,后续使用 <code>v-for</code> 渲染列表时,
    经常会处理类似的数据。
  </p>

  <hr>

  <h2>九、函数参数中的对象类型</h2>

  <p>
    对象类型也经常用于函数参数。
  </p>

  <pre><code>function printUser(user: { username: string; age: number }): void {
  console.log("用户名:" + user.username);
  console.log("年龄:" + user.age);
}

printUser({
  username: "jack",
  age: 18
});</code></pre>

  <p>
    这段代码中:
  </p>

  <ol>
    <li><code>user</code> 是函数参数。</li>
    <li><code>{ username: string; age: number }</code> 规定了参数对象的结构。</li>
    <li>调用函数时,传入的对象必须包含 <code>username</code> 和 <code>age</code>。</li>
  </ol>

  <p>
    下面这种调用是错误的:
  </p>

  <pre><code>printUser({
  username: "jack"
});</code></pre>

  <p>
    错误原因:
    参数对象缺少 <code>age</code> 属性。
  </p>

  <p>
    下面这种调用也是错误的:
  </p>

  <pre><code>printUser({
  username: "jack",
  age: "18"
});</code></pre>

  <p>
    错误原因:
    <code>age</code> 应该是数字,但传入了字符串。
  </p>

  <hr>

  <h2>十、对象类型写法较长时的问题</h2>

  <p>
    如果对象属性比较少,直接写对象类型还可以接受。
  </p>

  <pre><code>let user: { username: string; age: number } = {
  username: "jack",
  age: 18
};</code></pre>

  <p>
    但是,如果对象属性变多,类型写法就会变得很长。
  </p>

  <pre><code>let user: { username: string; age: number; address: string; isLogin: boolean } = {
  username: "jack",
  age: 18,
  address: "北京",
  isLogin: true
};</code></pre>

  <p>
    这种写法可以运行,但阅读起来不够方便。
    后面学习 <strong>类型别名</strong> 或 <strong>接口</strong> 后,
    可以把对象类型单独提取出来,让代码更清晰。
  </p>

  <p>
    当前阶段先掌握对象类型的基本写法即可。
  </p>

  <hr>

  <h2>十一、完整小示例</h2>

  <p>
    下面通过一个商品列表案例,综合演示对象类型和对象数组。
  </p>

  <pre><code>// 单个商品对象
let product: { name: string; price: number; inStock: boolean } = {
  name: "键盘",
  price: 199,
  inStock: true
};

// 商品数组
let productList: { name: string; price: number; inStock: boolean }[] = [
  { name: "键盘", price: 199, inStock: true },
  { name: "鼠标", price: 99, inStock: true },
  { name: "显示器", price: 899, inStock: false }
];

// 打印单个商品信息
function printProduct(item: { name: string; price: number; inStock: boolean }): void {
  console.log("商品名称:" + item.name);
  console.log("商品价格:" + item.price);
  console.log("是否有库存:" + item.inStock);
}

// 遍历商品数组
productList.forEach(function (item) {
  printProduct(item);
});

// 正确修改
product.price = 219;

// 错误示例
// product.price = "219";
// product.inStock = "有货";
// productList.push({ name: "音箱", price: "299", inStock: true });</code></pre>

  <p>
    这个案例中:
  </p>

  <ol>
    <li><code>product</code> 是一个商品对象。</li>
    <li><code>productList</code> 是商品对象数组。</li>
    <li><code>printProduct</code> 函数接收一个商品对象作为参数。</li>
    <li>商品名称必须是字符串。</li>
    <li>商品价格必须是数字。</li>
    <li>是否有库存必须是布尔值。</li>
  </ol>

  <p>
    对象类型可以让数据结构更明确,
    也能帮助我们在写代码时提前发现属性名或属性类型错误。
  </p>

  <hr>

  <h2>十二、本节总结</h2>

  <p>
    本节学习了 TypeScript 对象类型。
  </p>

  <ol>
    <li>对象用于保存一组相关数据。</li>
    <li>对象类型可以规定对象应该有哪些属性。</li>
    <li>对象类型可以规定每个属性的数据类型。</li>
    <li>对象类型中的属性名要和对象数据中的属性名对应。</li>
    <li>对象属性值的类型要和类型标注保持一致。</li>
    <li>对象缺少必需属性会报错。</li>
    <li>对象直接赋值时,多出未声明属性也可能报错。</li>
    <li>属性名后面加 <code>?</code> 可以表示可选属性。</li>
    <li>对象数组用于保存一组结构相同的对象。</li>
    <li>对象类型可以用于函数参数。</li>
    <li>对象类型写法较长时,后续可以使用类型别名或接口进行简化。</li>
  </ol>


</body>
</html>
相关推荐
稚南城才子,乌衣巷风流15 小时前
函数:编程中的核心概念
开发语言·前端·javascript
竹林81817 小时前
用 ethers.js 连接 MetaMask 实现钱包登录:一个真实项目中的完整踩坑记录
前端·javascript
虚惊一场17 小时前
在浏览器里跑 Prettier:格式化 Markdown 的四个难点
前端·javascript·vue.js
前端炒粉17 小时前
手撕小汇总
java·前端·javascript
虚惊一场17 小时前
把 CodeMirror 6 调教成 Markdown 编辑器:扩展、装饰与门面
前端·javascript·vue.js
虚惊一场18 小时前
一条 Markdown 渲染管线的全部细节:Worker、源行标注与按需加载
前端·javascript·vue.js
YIAN19 小时前
大模型总 "胡说八道"?用 LangChain.js 从零实现 RAG 语义检索系统
javascript·langchain
sugar__salt21 小时前
Vue.js 前置知识:ES6+ 核心特性完全指南
前端·javascript·vue.js·vue·es6
人间凡尔赛1 天前
世界模型入门实战:从RTFM到理解物理世界 | 2026深度技术解析
javascript·人工智能·深度学习·机器学习