日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

TypeScript中的對象類型(可選屬性 只讀屬性 交叉類型)

作者:jieyucx 更新時間: 2023-07-26 編程語言

一、定義對象類型

在TypeScript中定義對象類型有以下三種方式:

1. 匿名對象類型

匿名對象類型是在定義變量時直接使用花括號{},來定義一個對象類型。例如:

const person: { name: string, age: number } = { name: 'John', age: 25 };

上述代碼中定義了一個person變量,它的類型為對象,它有兩個屬性:name和age,其中name屬性的類型為字符串,age屬性的類型為數字。

2. 接口類型

使用接口來定義對象類型,可以使代碼更加可讀、易于維護。例如:

interface Person {
  name: string;
  age: number;
}

const person: Person = { name: 'John', age: 25 };

上述代碼中,定義了一個名為Person的接口,其中包括了兩個屬性:name和age。然后使用Person接口來定義了一個person變量,它的類型為Person接口。

3. 類型別名

使用類型別名可以為對象類型定義簡短、易讀的名稱。例如:

type Person = {
  name: string;
  age: number;
}

const person: Person = { name: 'John', age: 25 };

上述代碼中,使用type關鍵字定義了一個名為Person的類型別名,并通過花括號{}來定義了一個對象類型,其中有兩個屬性:name和age。然后使用Person類型別名來定義了一個person變量,它的類型為Person類型別名。

二、對象類型中的屬性修改器

1. 可選屬性

TypeScript中的可選屬性指的是,在定義對象類型時,可以設置一些屬性為可選屬性,即不是必須存在的屬性。具體的語法是在屬性名稱后面加上一個問號(?),如下所示:

interface Person {
  name: string;
  age?: number;
  gender?: string;
}

在上面的例子中,agegender是可選屬性。也就是說,在聲明一個Person類型的對象時,可以只包含name屬性,而不必提供agegender屬性。如果提供了這兩個屬性,它們的值必須符合對應的類型定義。

下面分多個角度舉例說明可選屬性的用法和好處。

(1). 增強代碼的靈活性

使用可選屬性可以增強代碼的靈活性,使得我們在聲明對象的時候可以根據需要選擇性地添加屬性,而不是強制要求屬性必須存在。這樣一來,一些在某些場景下沒有用處的屬性就不必被強制賦值了,節約了代碼修改的時間和精力。

舉個例子,我們在定義一個Book接口時,可以將authorpublisherdescription屬性都定義為可選屬性:

interface Book {
  title: string;
  author?: string;
  publisher?: string;
  description?: string;
}

然后在使用這個接口定義對象的時候,可以按照需求來添加這些屬性,比如:

const book1: Book = {
  title: 'TypeScript in Action',
  author: 'Erick Wendel'
};

const book2: Book = {
  title: 'JavaScript: The Good Parts',
  author: 'Douglas Crockford',
  publisher: 'Yahoo Press'
};

const book3: Book = {
  title: 'JavaScript: The Definitive Guide',
  author: 'David Flanagan',
  description: 'This book provides a complete description of the JavaScript language.'
};

在以上例子中,我們在聲明book1時只提供了titleauthor屬性,因為它們是必需的屬性。而在聲明book2時,我們增加了publisher屬性,因為這個屬性在這個場景下是有用的。在聲明book3時,我們只提供了titleauthor屬性,同時利用了description屬性來描述這本書的內容。所以,這樣的語法是非常方便的。

(2). 構建可靠的對象類型檢查

使用可選屬性還能幫助我們構建可靠的對象類型檢查。

在JavaScript中,我們會遇到無效的對象屬性,因為它們沒被正確地定義或被更新。這些錯誤通常很難發現,結果會導致代碼崩潰或是運行出現錯誤。

TypeScript可以用類型檢查來防止這種問題。通過定義對象屬性為可選屬性,我們可以預防掉對象屬性定義時的錯誤,從而構建可靠地類型檢查系統。如果屬性被定義成可選的,那么它可以沒有定義,而且也不會觸發錯誤。這樣我們就可以更容易地處理這些異常情形,從而提高代碼的可靠性和維護性。

下面是一個例子展示了使用可選屬性來保證類型檢查的可靠性:

interface Car {
  brand: string;
  model: string;
  year?: number;
}

function getCarInfo(car: Car): string {
  return `Brand: ${car.brand}, Model: ${car.model}${car.year ? `, Year: ${car.year}` : ''}`;
}

const car1: Car = { brand: 'Tesla', model: 'Model S', year: 2018 };
const car2: Car = { brand: 'BMW', model: 'X5' };
const car3: Car = { brand: 'Mercedes', model: 'E220', year: '2021' };

console.log(getCarInfo(car1)); // Brand: Tesla, Model: Model S, Year: 2018
console.log(getCarInfo(car2)); // Brand: BMW, Model: X5
console.log(getCarInfo(car3)); // Brand: Mercedes, Model: E220

在上面的例子中,我們定義了一個Car接口,并定義year屬性為可選屬性。可以清晰地看到,我們在getCarInfo函數中使用了year屬性的值來返回車的信息。當year屬性可選時,我們在獲取year屬性時需要先檢查它是否存在,否則輸出的字符串結果將不符合我們預期。在car3的定義中,我們給year屬性賦的值是一個字符串型而不是數字型,這時TypeScript會提示錯誤。

(3). 提供默認屬性值

除了類型檢查外,我們還可以用可選屬性來提供默認屬性值。在某些場景下,如果對象的某些屬性沒有被定義,那么我們可以提供一個默認值,以確保代碼可以正常運行。

舉個例子,在定義一個Product接口時可以使用可選屬性提供一個price屬性的默認值,如下所示:

interface Product {
  name: string;
  price?: number;
}

const shirt: Product = { name: 'Shirt' };
const pants: Product = { name: 'Pants', price: 45.00 };

console.log(shirt.price || 15.00); // 15
console.log(pants.price || 15.00); // 45

在上面的例子中,我們給shirt對象定義了一個默認的price屬性值為15,在打印price屬性時,因為shirt對象沒有定義price屬性,所以輸出的值是默認值15。而在打印pantsprice屬性時,因為pants對象定義了price屬性,輸出的是45,這是由于該屬性已定義的值是45。

2. 只讀屬性

TypeScript中,我們可以聲明一個對象類型中的屬性為只讀屬性,即該屬性的值一旦被賦值就不能再被修改。

舉例來說,假設有一個Student類型的對象,其中包含學生的姓名和年齡。我們可以將學生的姓名聲明為只讀屬性,代碼如下:

type Student = {
  readonly name: string;
  age: number;
}

在上述代碼中,我們使用了readonly關鍵字來將name屬性聲明為只讀屬性。這意味著一旦我們給該屬性賦值,就無法再修改它的值。

下面再舉一個例子,假設我們有一個Point類型的對象,包含了二維平面上的坐標x和y。我們可以將該對象中的x和y屬性都聲明為只讀屬性,以保證對象的坐標值不會被意外修改。代碼如下:

type Point = {
  readonly x: number;
  readonly y: number;
}

const p: Point = { x: 0, y: 0 };

// 錯誤,無法修改只讀屬性
p.x = 10;

在上述代碼中,我們使用了readonly關鍵字將Point類型中的x和y屬性都聲明為只讀屬性。在給p對象中的x屬性賦值之后,我們試圖修改該屬性的值,但是因為它是只讀屬性,所以會編譯錯誤。

3. 索引簽名

在 TypeScript 中,對象類型可以包含索引簽名,以支持在動態屬性上訪問屬性值。索引簽名允許您在對象類型中定義一個模式,該模式指定應該具有哪些屬性和屬性類型。以下是一個示例:

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

const exampleObject: ExampleObject = {
  property1: "value1",
  property2: "value2",
  // ...
};

這里的索引簽名 [key: string]: string 意味著對象 ExampleObject 中的所有屬性的鍵都是字符串,所有屬性的值都是字符串。因此,可以使用類似于 exampleObject.property1 這樣的關鍵字為其屬性賦值或訪問屬性值。

下面是一些其他角度的示例:

  1. 在對象類型中使用數字索引簽名,以表示索引為數字的屬性:
interface ExampleObject {
  [key: number]: string;
}

const exampleObject: ExampleObject = {
  0: "value1",
  1: "value2",
  // ...
};
  1. 在對象類型中使用只讀索引簽名,以表示不希望在運行時更改的屬性:
interface ExampleObject {
  readonly [key: string]: string;
}

const exampleObject: ExampleObject = {
  property1: "value1",
  property2: "value2",
  // ...
};

exampleObject.property1 = "new value"; // This will cause a TypeScript error
  1. 在對象類型中使用聯合類型索引簽名,以表示可以具有多個類型的屬性:
interface ExampleObject {
  [key: string]: string | number;
}

const exampleObject: ExampleObject = {
  property1: "value1",
  property2: 2,
  // ...
};

在這個示例中,屬性的值可以是字符串或數字。

4. 擴展類型

TypeScript中的對象類型是通過接口來定義的,接口可以擴展其他接口,從而實現對象類型的擴展。

例如,我們可以定義一個基礎的對象類型接口Person,然后定義一個Student接口來繼承Person接口并添加一些額外的屬性:

interface Person {
  name: string;
  age: number;
}

interface Student extends Person {
  school: string;
  grade: string;
}

這樣,Student接口就包含了Person接口中所有的屬性,同時添加了school和grade屬性。

5. 交叉類型

交叉類型(Intersection Types)是Typescript中的一種類型操作符,用于將多個類型合并成一個類型。它的語法是將多個類型通過 & 連接起來,例如:

type Person = {
  name: string;
  age: number;
};
type Employee = {
  employer: string;
  salary: number;
};

type Worker = Person & Employee;

在上面的例子中,我們定義了兩個類型Person和Employee,并將它們通過 & 連接起來得到了一個新的類型Worker。這個新類型包含了兩個原類型中的所有屬性。

與交叉類型類似的還有聯合類型(Union Types),用于將多個類型中的一個合并成一個類型,并采用 | 連接。

交叉類型和interface的extends擴展類型的區別

與交叉類型相比,使用interface的extends擴展類型可以實現類似的效果,但是它們的設計思想不同。extends用于在一個類型基礎上擴展屬性和方法,而交叉類型則是將多個類型合并起來以創建一個新的類型

例如,我們定義了一個接口Animal:

interface Animal {
  name: string;
  eat(): void;
}

然后定義了兩個接口Dog和Person,并通過extends方式擴展了它們的屬性和方法:

interface Dog extends Animal {
  bark(): void;
}

interface Person extends Animal {
  age: number;
  speak(): void;
}

上面代碼中,Dog和Person都擴展了Animal接口,即它們都繼承了Animal中的name屬性和eat方法。與交叉類型不同的是,Dog和Person無法同時擁有Animal以外的屬性和方法。

綜上所述,交叉類型和extends擴展類型雖然都用于繼承和合并類型,但是它們的應用場景和用途不同。交叉類型適合于將多個類型合并為一個類型,而extends擴展類型適合于在一個類型基礎上擴展屬性和方法。在不同的場景中,我們可以選擇不同的方式來定義和組合類型。

6. 泛型對象類型

泛型對象類型可以用于對象屬性中的類型聲明。例如,以下代碼定義了一個對象類型,該對象具有不同類型的屬性:

interface List<T> {
  data: T[]
  add: (item: T) => void
}

const list1: List<string> = {
  data: ['hello', 'world'],
  add(item) {
    this.data.push(item)
  }
}

const list2: List<number> = {
  data: [1, 2],
  add(item) {
    this.data.push(item)
  }
}

在上面的代碼中,<T>表示泛型對象類型,我們在List<T>中使用了該類型,以聲明data屬性和add方法的參數和返回類型。

原文鏈接:https://blog.csdn.net/jieyucx/article/details/131347619

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新