在我们的 前一篇关于TypeScript Mixins的帖子中,我们简短地谈到了TypeScript中的声明合并,在这些帖子系列中,我们将从与界面声明合并的界面开始深入一点。
什么是声明合并?
声明合并是当TypeScript编译器将两个或多个类型合并为一个声明时,只要它们具有相同的名称。
TypeScript 允许多种类型的合并,如界面
与界面
,enum
与enum
,namespace
与namespace
等。
让我们从界面
和界面
合并开始,看看一个例子:
1interface Person {
2 name: string;
3}
4
5interface Person {
6 age: number;
7}
8
9interface Person {
10 height: number;
11}
12
13class Employee implements Person {
14 name = "Mensah"
15 age = 100;
16 height = 40
17}
18
19const employee = new Employee();
20console.log(employee) // {name: "Mensah", age: 100, height: 40}
由于所有界面都被声明为同名人
,因此它们被合并为一个定义,因此员工
类包含所有界面的属性。
接口中的相同属性名称(非函数)
如果将合并的任何接口都包含相同的属性名称,而该属性不是函数,那么属性的类型
必须是相同的,否则编译器会引发错误。
1interface Person {
2 name: string;
3 zipCode: string;
4}
5
6interface Person {
7 age: number;
8 zipCode: string; // acceptable
9}
10
11interface Person {
12 zipCode: number; // error
13}
界面上相同的属性名称(功能)
当合并界面中的元素是函数,并且它们具有相同的名称时,它们会被过载,也就是说,取决于通过的参数的类型
,将调用相应的函数。
1interface Person {
2 speak(words: string);
3}
4
5interface Person {
6 speak(words: number);
7}
8
9const person: Person = {
10 speak: (wordsOrNum) => wordsOrNum
11}
12
13console.log(person.speak("Hi")) // speak(words: string) is used
14console.log(person.speak(2)) // speak(words: number) is used
当包含相同签名函数的接口合并时,最后宣布的接口中的函数出现在合并接口的顶部,第一个接口中宣布的函数出现在下方。
1interface Person {
2 speak(words:string);
3}
4
5interface Person {
6 speak(words: any);
7}
8
9interface Person {
10 speak(words: number);
11 speak(words: boolean);
12}
13
14// This is how the final merged interface looks like
15interface Person {
16 // functions in the last interface appear at the top
17 speak(words: number);
18 speak(words: boolean);
19
20 // function in the middle interface appears next
21 speak(words: any):number;
22
23 // function in the first interface appears last
24 speak(words: string):string;
25}
因此,在我们上面的例子中,‘speak(words: string)’永远不会被调用,因为在最终合并的‘Person’接口中,‘speak(words: any):number’在‘speak(words: string):string’之前出现,并且由于‘any’可以代表任何类型,即使一个‘string’被传递为‘argument’,它也会被调用。
为了证明这一点,当您在下面的代码中横跨per
变量时,它会显示const per:number
,而不是const per: string
,即使我们正在通过一个字符串
参数。
1const per = person.speak("bacon");
这适用于所有接口 expect,当相同名称函数参数具有字母字符串(https://andsky.com/tech/tutorials/typescript-string-literal-types)作为类型
。它遵循上述相同的顺序,但具有字母字符串类型的函数具有更高的优先级,因此出现在顶部。
值得注意的是,后续界面中的字符串字母会像上面解释的那样出现在初始界面之前。
1interface Person {
2 speak(words: number);
3 speak(words: "World!"); // string literal type
4}
5
6interface Person {
7 speak(words: "Hello"); // string literal type
8}
9
10interface Person {
11 speak(words: string);
12}
13
14// merged interface output.
15interface Person {
16 // string literals are given precedence
17 speak(words: "Hello");
18 speak(words: "World!");
19
20 // the rest of the functions are arranged using the same rules.
21 speak(words: string);
22 speak(words: number);
23}
希望有用!希望有用!