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