statement merge
类型合并
Indicates 编译器
that 合并
two 分开
and the 名称
same statement, the 合并
latter 声明
has 声明
the characteristics of two, any number of 声明
can be combined, not only 两个
.
Merge Interface
1. interface
The non-function members of 1. should be unique. If both interface
declare one 名称相同但类型不同
, 非函数成员
an 编译器
error will be prompted:
interface Box {
height: number;
}
interface Box {
height: string;
}
复制代码
2. For 函数成员
, members of each 相同名称
are seen as 相同名称函数的重载
, but when there are two interface
, the 第二个有更高的优先
class, overrides the previous one:
interface Cloner {
clone(animal: Animal): Animal;
}
interface Cloner {
clone(animal: Sheep): Sheep;
}
interface Cloner {
clone(animal: Dog): Dog;
clone(animal: Cat): Cat;
}
// 最终的排序是
interface Cloner {
clone(animal: Dog): Dog;
clone(animal: Cat): Cat;
clone(animal: Sheep): Sheep;
clone(animal: Animal): Animal;
}
复制代码
Of course there is an exception to this rule, when the parameter type of the function is a 单字面量类型
(single string literal type), it will be 优先级排序
placed according to 声明顶部
:
interface Document {
createElement(tagName: any): Element;
}
interface Document {
createElement(tagName: 'div'): HTMLDivElement;
createElement(tagName: 'span'): HTMLSpanElement;
}
interface Document {
createElement(tagName: string): HTMLElement;
createElement(tagName: 'canvas'): HTMLCanvasElement;
}
// 字面量根据冒泡排序并放在了声明顶部
interface Document {
createElement(tagName: 'canvas'): HTMLCanvasElement;
createElement(tagName: 'div'): HTMLDivElement;
createElement(tagName: 'span'): HTMLSpanElement;
createElement(tagName: string): HTMLElement;
createElement(tagName: any): Element;
}
复制代码
Merge Namespaces
- When merging two of the same name
namespace
, the second will be further addednamespace
to导出的成员
the firstnamespace
.
namespace Animals {
export class Zebra {}
}
namespace Animals {
export interface Legged {
numberOfLegs: number;
}
export class Dog {}
}
// 合并到了第一个
namespace Animals {
export interface Legged {
numberOfLegs: number;
}
export class Zebra {}
export class Dog {}
}
复制代码
- When a
namespace
merge occurs, the merged with itnamesapce
cannot access it未导出的成员
:
namespace Animal {
const haveMuscles = true;
export function animalsHaveMuscles() {
return haveMuscles;
}
}
namespace Animal {
export function doAnimalsHaveMuscles() {
return haveMuscles; // Error, because haveMuscles is not accessible here
}
}
复制代码
It can be seen that it cannot be accessed
haveMuscles
, and an error will be reported when running at the same time. You can see it in conjunction with the compiled example:
namespace and class, enum, function merge
- As with merging
namespace
, the exported sumclass
can be accessed in :namespace
类型
值
class Album {
label: Album.AlbumLabel;
}
namespace Album {
export class AlbumLabel {}
}
复制代码
namespace
andfunction
merge canjavascript
add attributes on methods like this:
function buildLabel(name: string): string {
return buildLabel.prefix + name + buildLabel.suffix;
}
namespace buildLabel {
export const suffix = '';
export const prefix = 'Hello, ';
}
console.log(buildLabel('Sam Smith'));
复制代码
You can look at the compiled code, and you can see that buildLabel
the attributes are added directly on:
namespace
andenum
when a merge occurs,namespace
it can be extendedenum
enum Color {
red = 1,
green = 2,
blue = 4,
}
namespace Color {
export function mixColor(colorName: string) {
if (colorName == 'yellow') {
return Color.red + Color.green;
} else if (colorName == 'white') {
return Color.red + Color.green + Color.blue;
} else if (colorName == 'magenta') {
return Color.red + Color.blue;
} else if (colorName == 'cyan') {
return Color.green + Color.blue;
}
}
}
复制代码
You can see after compilation:
Merging between classes is not allowed, but if you need to imitate similar functions, you can refer to Mixins in Typscripts
Module extension
Although Module
merging between them is not supported, you can implement it by importing 扩展
the required method and then using 更改
it:
// observable.ts
export class Observable<T> {
// ... implementation left as an exercise for the reader ...
}
// map.ts
import { Observable } from "./observable";
Observable.prototype.map = function (f) {
// ... another exercise for the reader
};
复制代码
But this way the compiler doesn't provide good hints, so an extended module
declaration is required:
// observable.ts
export class Observable<T> {
// ... implementation left as an exercise for the reader ...
}
// map.ts
import { Observable } from "./observable";
declare module "./observable" {
interface Observable<T> {
map<U>(f: (x: T) => U): Observable<U>;
}
}
// 扩展声明
Observable.prototype.map = function (f) {
// ... another exercise for the reader
};
// consumer.ts
import { Observable } from "./observable";
import "./map";
let o: Observable<number>;
o.map((x) => x.toFixed());
复制代码
Global expansion
If it is in a module, it can also be 全局声明中
extended here:
// observable.ts
export class Observable<T> {
// ... still no implementation ...
}
// 在这里扩展
declare global {
interface Array<T> {
toObservable(): Observable<T>;
}
}
Array.prototype.toObservable = function () {
// ...
};
复制代码
ReferencesDeclaration Merging