typescript 中的 extends 关键字就像一把瑞士军刀。它可用于多种上下文,包括继承、泛型和条件类型。了解如何有效地使用扩展可以生成更健壮、可重用且类型安全的代码。
extends 的主要用途之一是继承,允许您创建基于现有接口或类的新接口或类。
interface user { firstname: string; lastname: string; email: string; } interface staffuser extends user { roles: string[]; department: string; } const regularuser: user = { firstname: "john", lastname: "doe", email: "john@example.com" }; const staffmember: staffuser = { firstname: "jane", lastname: "smith", email: "jane@company.com", roles: ["manager", "developer"], department: "engineering" };
在此示例中,staffuser 扩展了 user,继承了其所有属性并添加了新属性。这使我们能够基于更通用的类型创建更具体的类型。
extends 关键字也用于类继承:
class animal { constructor(public name: string) {} makesound(): void { console.log("some generic animal sound"); } } class dog extends animal { constructor(name: string, public breed: string) { super(name); } makesound(): void { console.log("woof! woof!"); } fetch(): void { console.log(`${this.name} is fetching the ball!`); } } const mydog = new dog("buddy", "golden retriever"); mydog.makesound(); // output: woof! woof! mydog.fetch(); // output: buddy is fetching the ball!
这里,dog 扩展了 animal,继承了它的属性和方法,同时还添加了它自己的属性和方法。
extends 关键字在使用泛型时至关重要,它允许我们限制可与泛型函数或类一起使用的类型。
interface printable { print(): void; } function printobject<t extends printable>(obj: t) { obj.print(); } class book implements printable { print() { console.log("printing a book."); } } class magazine implements printable { print() { console.log("printing a magazine."); } } const mybook = new book(); const mymagazine = new magazine(); printobject(mybook); // output: printing a book. printobject(mymagazine); // output: printing a magazine. // printobject(42); // error, number doesn't have a 'print' method </t>
总之,函数 printobject
t extends u ? x : y
type extractnumber<t> = t extends number ? t : never; type numberornever = extractnumber<number>; // number type stringornever = extractnumber<string>; // never </string></number></t>
这里,extractnumber 类型采用类型参数 t。条件类型检查 t 是否扩展了数字类型。如果是,则类型解析为 t(这是数字类型)。如果不存在,则类型解析为 never。
现在,让我们考虑表达式 a |乙| c 扩展了 a。乍一看这似乎违反直觉,但在 typescript 中,这个条件实际上是错误的。原因如下:
type Fruit = "apple" | "banana" | "cherry"; type CitrusFruit = "lemon" | "orange"; type IsCitrus<t> = T extends CitrusFruit ? true : false; type Test1 = IsCitrus; // true type Test2 = IsCitrus; // false type Test3 = IsCitrus<fruit>; // false </fruit></t>
在此示例中,iscitrus