在我们的 上一篇关于 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); }
就是这样。 希望这很有用。 😊😎