注意: 如果您是 TypeScript 新手,请先查看我们的 TypeScript 入门 教程。
对象是键值对的集合。
在 TypeScript 中,对象类型允许您定义对象的结构——它应该有哪些属性,以及这些属性应该是什么类型。
这是一个简单的对象示例。您可以阅读本教程的其余部分以了解更多信息。
示例
let user: { name: string; age: number } = {
name: "Alice",
age: 25
};
在这里,user 是一个具有两个属性的对象:name(字符串类型)和 age(数字类型)。
定义对象类型
在 TypeScript 中,您可以通过三种主要方式定义对象类型
1. 内联对象类型
内联对象类型是指在声明变量时直接定义对象的结构(就像在入门示例中看到的那样)。
let user: { name: string; age: number } = {
name: "Alice",
age: 25
};
在这里,{ name: "Alice", age: 25 } 是赋给 user 变量的对象。
2. 使用类型别名
您也可以使用 type 关键字创建对象类型。
type Person = {
name: string;
age: number;
};
let user: Person = { name: "Sara", age: 22 };
在这里,type Person = { ... } 创建了一个名为 Person 的类型别名,并定义了一个有效的 Person 对象应该是什么样的:它必须有两个属性——name(字符串)和 age(数字)。
然后,我们将对象 { name: "Sara", age: 22 } 赋给类型为 Person 的 user 变量。
注意:当您想在多个地方重用对象类型时,可以使用类型别名。
3. 使用接口
您也可以使用 interface 关键字来定义对象的结构。
interface Person {
name: string;
age: number;
}
let user: Person = { name: "Tom", age: 28 };
在这里,Person 是一个接口,它描述了一个具有两个属性的对象:name(字符串类型)和 age(数字类型)。
可选属性 (?)
您可以使用 ? 将属性标记为可选——这意味着对象可以包含该属性,但不是必需的。例如,
type User = { name: string; age?: number };
type Person = { name: string; age?: number };
// Valid
let user1: Person = { name: "Alice", age: 25 };
// Valid even though age is missing
let user2: Person = { name: "Bob" };
在此示例中,age 是可选的。因此,user1 和 user2 都是有效的——一个包含 age,另一个则不包含。
对象类型作为函数参数
您还可以为函数参数使用对象类型,以精确定义传递到函数中的对象应该具有哪些属性。例如,
function greet(user: { name: string; age: number }) {
console.log(`Hello, ${user.name}. You are ${user.age} years old.`);
}
greet({ name: "Tyler", age: 43 });
在这里,greet() 函数期望一个具有两个属性的对象:name(字符串)和 age(数字)。
常见问题
当将对象作为参数传递给函数时,您可以使用解构来提取特定属性——并且还可以提供默认值以防这些属性丢失。
function draw({ x = 0, y = 0 }: { x?: number; y?: number }) {
console.log(x, y);
}
draw({ x: 10 }); // Output: 10 0
draw({}); // Output: 0 0
在这里,draw() 函数接受一个带有可选 x 和 y 属性的对象。使用带有 x = 0 和 y = 0 的解构提供了默认值。
如果未传递 x 或 y,它将默认为 **0** 而不是 undefined。
对象的只读属性
readonly 关键字使属性变为只读,这意味着您不能重新分配它。例如,
type Home = {
readonly resident: { name: string };
};
const house: Home = {
resident: { name: "Alice" }
};
// Error: Cannot assign to 'resident' because it is a read-only property
house.resident = { name: "Bob" };
在这里,resident 属性被标记为 readonly,因此当我们尝试重新分配 resident 对象时,如下所示
house.resident = { name: "Bob" };
TypeScript 会抛出错误,因为 readonly 防止了属性的重新分配。
但是,由于内部的 name 属性未标记为 readonly,我们仍然可以修改它
house.resident.name = "Charlie"; // This works
使用索引签名定义对象
索引签名允许您定义具有动态属性名称的对象——这意味着您不必预先知道属性名称,但仍然可以指定值的类型。
type Scores = { [subject: string]: number };
const mathScores: Scores = {
math: 95,
science: 88,
english: 76
};
在这里,[subject: string]: number 表示对象可以有任意数量的 string 键,并且每个键都必须有一个 number 值。
常见问题
您可以使用 & (交叉类型)将多个对象类型组合成一个。结果类型必须满足所有组合类型的属性。例如,
type User = { name: string };
type Admin = { role: string };
type AdminUser = User & Admin;
const admin: AdminUser = {
name: "Alice",
role: "Super Admin"
};
在这里,AdminUser 使用 & 组合了 User 和 Admin,因此它必须同时具有 name 和 role 属性。
另请阅读