您的位置:

深入了解 TypeScript 中的对象类型

一、基本概念

在 TypeScript 中,对象类型可以通过字面量表示法来定义一个对象。字面量表示法可以定义一个对象的属性名和属性值,然后将其放在一对花括号中,以表示一个对象。

{
    name: string,
    age: number,
    phone?: string
}

此处定义了一个对象类型,它包含三个属性:name、age 和 phone,其中 phone 属性是可选属性,表示该属性可以存在也可以不存在。

对象类型还可以使用接口(interface)或类型别名(type)来定义:

interface Person {
    name: string,
    age: number,
    phone?: string
}
type PersonAgain {
    name: string,
    age: number,
    phone?: string
}

这里以接口为例,定义了一个名为 Person 的接口,其属性与上面的字面量表示法一致。

二、属性修饰符

在对象类型中,属性可以具有以下修饰符:

  • readonly:表示该属性只读(不可修改)
  • public:表示该属性是公共属性(默认值,可以在任何地方访问)
  • private:表示该属性是私有属性(只能在类内部访问)
  • protected:表示该属性是受保护属性(只能在基类或其子类内部访问)

示例代码如下:

interface Point {
    readonly x: number,
    readonly y: number,
    z?: number
}

class PointThreeD implements Point {
    readonly x: number;
    readonly y: number;
    readonly z: number;

    constructor(x: number, y: number, z: number) {
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

let p3d = new PointThreeD(1, 2, 3);
console.log(p3d.x); // 输出 1
p3d.x = 4; // 报错,属性 'x' 只读

在这个例子中,定义了一个名为 Point 的接口,它包含两个只读属性:x 和 y,以及一个可选属性 z。并且还定义了一个名为 PointThreeD 的类,该类对接口 Point 进行实现,并在构造函数中为所有属性赋值。p3d 为 PointThreeD 类型的一个实例,可以访问其属性 x、y 和 z(只有 PointThreeD 类型才有 z 属性)。

三、键名签名

在 TypeScript 中,对象类型还可以使用键名签名来定义一系列属性。键名签名包含两个部分:键名类型和键值类型。

interface Dict {
  [key: string]: string;
}

let dict: Dict = {
  name: 'Tom',
  age: '18',
  phone: '1234567890'
};

在这个例子中,定义了一个名为 Dict 的接口,它包含一个键名为 string 类型、键值为 string 类型的键名签名。dict 为 Dict 类型的一个实例,可以访问其所有键值。

四、交叉类型

交叉类型(Intersection Types)表示多个类型的交集。通过交叉类型,我们可以将多个对象类型合并成一个对象类型。

interface User {
  name: string;
  age: number;
}
interface UserInfo {
  city: string;
  occupation: string;
}
type UserAndInfo = User & UserInfo;

let user: UserAndInfo = {
  name: 'Tom',
  age: 18,
  city: 'Beijing',
  occupation: 'Engineer'
}

在这个例子中,定义了两个接口 User 和 UserInfo,它们分别定义了用户和用户信息的属性。接着定义了一个名为 UserAndInfo 的类型别名,它是 User 类型和 UserInfo 类型的交集。最后定义了一个 user 对象为 UserAndInfo 类型,可以访问其属性 name、age、city 和 occupation。

五、联合类型

联合类型(Union Types)表示多个类型的并集。通过联合类型,我们可以将多种不同对象类型合并成一个对象类型。

interface Cat {
    type: 'cat',
    name: string,
    sound: string
}

interface Dog {
    type: 'dog',
    name: string,
    sound: string
}

type CatAndDog = Cat | Dog;

function playSound(animal: CatAndDog) {
    console.log(animal.sound);
}

let cat = { type: 'cat', name: 'Tom', sound: 'Meow' };
let dog = { type: 'dog', name: 'Jerry', sound: 'Bark' };

playSound(cat); // 输出 'Meow'
playSound(dog); // 输出 'Bark'

在这个例子中,定义了两个接口 Cat 和 Dog,它们分别定义了猫和狗的属性。接着定义了一个名为 CatAndDog 的联合类型,它是 Cat 类型和 Dog 类型的并集。最后定义了一个 playSound 函数,该函数的参数 animal 可以是 CatAndDog 类型,然后在函数体内输出 animal 的声音。

六、索引类型

索引类型(Index Types)允许我们动态地访问和操作对象的属性。在 TypeScript 中,索引类型有两种:字符串索引和数字索引。

字符串索引允许我们使用字符串来访问对象的属性:

interface Dict {
  [key: string]: string;
}
let dict: Dict = {};
dict['name'] = 'Tom';
dict['age'] = '18';

在这个例子中,定义了一个名为 Dict 的接口,它包含一个字符串索引,其键类型为 string,值类型为 string。然后定义了一个 dict 对象为 Dict 类型,可以动态地向 dict 对象中添加属性和属性值。

数字索引允许我们使用数字来访问对象的属性:

interface NumberArray {
    [index: number]: number;
}
let arr: NumberArray = [1, 2, 3];
let num: number = arr[0];

在这个例子中,定义了一个名为 NumberArray 的接口,它包含一个数字索引,其键类型为 number,值类型为 number。然后定义了一个 arr 对象为 NumberArray 类型,可以动态地添加数字类型的属性和属性值。

七、总结

在 TypeScript 中,对象类型是一个非常重要的概念。通过对象类型的深入了解,我们可以更好地理解 TypeScript 语法,从而提高我们的编程效率。