可以看出,
命名空间的声明,创建一个命名空间和一个值
;变量的声明只会创建一个值;interface 和 type 的声明只会创建一个类型;
而
class
和
enum
的声明,既会创建一个值,也会创建一个同名的类型
。
二、合并
interface
接口
interface的合并是最简单、最常见的声明合并。主要声明多个同名的 interface ,TS就会自动将其合并。但是这些 interface 中,如果有同名的非函数字段,则该字段对应的类型也应该相同,否则会被标记为错误。
interface A {
name: string,
age: number,
interface A {
name: string,
gender: 1 | 2,
interface B {
name: string,
age: number,
interface B {
age: string,
gender: 1 | 2,
而在interface的合并中,同名的函数则会被视为同一函数的重载,且后声明的接口具有更高的优先级。
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;
但是,有一种情况会例外:当函数签名里,存在一个类型是单一的字符串型的字面量(不是联合类型的字面量)的参数时,这个签名就会被置于最前面。
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;
三、合并 namespace
命名空间
和 interface 的合并类似,声明的同名namespace也会合并每个声明的成员。由于namespace会创建namespace和值,命名空间和值都会合并。
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 {}
在 namespace 的声明中,没有被 export
的成员,无法在另一个同名的namespace中获取,也无法使用namespace的名字来访问。
namespace Person {
let name = "cc"
export function getName(){
return name
namespace Person {
export function setName(str: string){
name = str
在上面的栗子中,由于在第一个namespace中,name没有被导出,因此在第二个namespace中,无法获取到name。只需要经过 export ,就可以在其它同名的namespace中共享该成员了。
namespace Person {
export let name = "cc"
export function getName(){
return name
namespace Person {
export function setName(str: string){
name = str
四、将 Namespaces
与 Classes
、Functions
、Enums
合并
1. 合并命名空间与类
在命名空间中导出的成员,会成为同名的class的静态成员,而没有导出的成员,则无法在被class获取。
class Album {
label: Album.AlbumLabel;
namespace Album {
export class AlbumLabel {};
export const name = "cc";
let age = 18;
Album.name
Album.age
const album = new Album()
album.name
2. 合并 命名空间 与 函数
命名空间中导出的成员,会成为同名函数的属性。
function logName(str: string){
console.log(str + logName.name)
namespace logName {
export const name = "cc"
export const age = 18
let gender = 1
logName("yy")
3. 合并 命名空间 和 枚举
合并命名空间和枚举,会将命名空间导出的成员作为枚举的扩充。
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;
export const pink = 10
Color.mixColor("yellow")
Color.pink
另外还有模块扩充和全局扩充,在这里就不介绍了。下一篇,就讲讲 枚举 Enums
吧。