TypeScript中的接口声明合并
在我们的 上一篇关于 TypeScript Mixins 的文章中,我们简要讨论了 TypeScript 中的声明合并。 在这一系列文章中,我们将从接口声明合并的接口开始更深入一些。
什么是声明合并?
声明合并是 TypeScript 编译器将两个或多个类型合并到一个声明中,前提是它们具有相同的名称。
TypeScript 允许在多种类型之间进行合并,例如 interface 与 interface、enum 与 enum、namespace 与 namespace、等等 一个值得注意的不允许合并是 class 与 class 合并。 如果您想要这样的功能,请查看 mixins。
让我们通过查看一个示例开始使用 interface 与 interface 合并:
interface Person {
name: string;
}
interface Person {
age: number;
}
interface Person {
height: number;
}
class Employee implements Person {
name = "Mensah"
age = 100;
height = 40
}
const employee = new Employee();
console.log(employee) // {name: "Mensah", age: 100, height: 40}
由于所有接口都使用相同的名称 Person 声明,因此它们被合并到一个定义中,因此 Employee 类包含来自所有接口的属性。
接口中的相同属性名称(非函数)
如果要合并的任何接口包含相同的属性名称并且该属性不是函数,则属性的 type 必须相同,否则编译器将抛出错误。
interface Person {
name: string;
zipCode: string;
}
interface Person {
age: number;
zipCode: string; // acceptable
}
interface Person {
zipCode: number; // error
}
接口(函数)中的相同属性名称
当合并的接口中的元素是函数并且它们具有相同的名称时,它们被重载,即根据传递的参数的type,将调用相应的函数。
interface Person {
speak(words: string);
}
interface Person {
speak(words: number);
}
const person: Person = {
speak: (wordsOrNum) => wordsOrNum
}
console.log(person.speak("Hi")) // speak(words: string) is used
console.log(person.speak(2)) // speak(words: number) is used
当包含相同签名函数的接口被合并时,最后声明的接口中的函数出现在合并接口的顶部,而第一个接口中声明的函数出现在下面。
interface Person {
speak(words:string);
}
interface Person {
speak(words: any);
}
interface Person {
speak(words: number);
speak(words: boolean);
}
// This is how the final merged interface looks like
interface Person {
// functions in the last interface appear at the top
speak(words: number);
speak(words: boolean);
// function in the middle interface appears next
speak(words: any):number;
// function in the first interface appears last
speak(words: string):string;
}
这样做的原因是,后来声明的接口比最初声明的接口具有更高的优先级。 所以在我们上面的例子中,speak(words: string) 永远不会被调用,因为在最终合并的 Person 接口中,speak(words: any):number 出现在 speak(words: string):string 之前并且因为 [X152X ] 可以代表任何类型,即使 string 作为 argument 传递,它也会被调用。
为了证明这一点,当您将鼠标悬停在下面代码中的 per 变量上时,它会显示 const per: number 而不是 const per: string 即使我们传入 [X157X ] 争论。
const per = person.speak("bacon");
当同名函数参数具有 字符串文字 作为 type 时,所有接口 expect 都是如此。 它遵循上述相同的顺序,但具有字符串文字类型的函数具有更高的优先级,因此出现在顶部。
值得注意的是,后面的接口中的字符串文字会出现在上面解释的初始接口之前。
interface Person {
speak(words: number);
speak(words: "World!"); // string literal type
}
interface Person {
speak(words: "Hello"); // string literal type
}
interface Person {
speak(words: string);
}
// merged interface output.
interface Person {
// string literals are given precedence
speak(words: "Hello");
speak(words: "World!");
// the rest of the functions are arranged using the same rules.
speak(words: string);
speak(words: number);
}
就是这样。 希望这很有用。 😊😎