添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

可以看出, 命名空间的声明,创建一个命名空间和一个值 ;变量的声明只会创建一个值;interface 和 type 的声明只会创建一个类型; class enum 的声明,既会创建一个值,也会创建一个同名的类型

二、合并 interface 接口

interface的合并是最简单、最常见的声明合并。主要声明多个同名的 interface ,TS就会自动将其合并。但是这些 interface 中,如果有同名的非函数字段,则该字段对应的类型也应该相同,否则会被标记为错误。

interface A {
  name: string,
  age: number,
interface A {
  // 同名字段name,对应的类型也相同,
  name: string,
  gender: 1 | 2,
interface B {
  name: string,
  age: number,
interface B {
  // 报错,同名字段age,对应的类型不同,分别为number和string
  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的名字来访问

// name 没有被 export 导出
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中共享该成员了。

// name 没有被 export 导出
namespace Person {
  export let name = "cc"
  export function getName(){
    return name
namespace Person {
  export function setName(str: string){
    name = str

四、将 NamespacesClassesFunctionsEnums 合并

1. 合并命名空间与类

在命名空间中导出的成员,会成为同名的class的静态成员,而没有导出的成员,则无法在被class获取。

class Album {
  label: Album.AlbumLabel;
namespace Album {
  export class AlbumLabel {};
  export const name = "cc";
  let age = 18;
Album.name  // "cc"
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")  // 3
Color.pink  // 10

另外还有模块扩充和全局扩充,在这里就不介绍了。下一篇,就讲讲 枚举 Enums 吧。

分类:
前端
标签: