TypeScript错误TS1183:无法在环境上下文中声明实现

时间:2019-07-01 10:39:16

标签: typescript

为什么我会从TS教程收到相同的代码错误而又不会抛出错误?

从教程(https://www.typescriptlang.org/docs/handbook/namespaces.html#namespacing):

  1. 命名空间。
  2. 名称空间内的接口
  3. 类实现接口
  4. 类实现方法
namespace Validation {
    export interface StringValidator {
        isAcceptable(s: string): boolean;
    }

    const lettersRegexp = /^[A-Za-z]+$/;
    const numberRegexp = /^[0-9]+$/;

    export class LettersOnlyValidator implements StringValidator {
        isAcceptable(s: string) {
            return lettersRegexp.test(s);
        }
    }

    export class ZipCodeValidator implements StringValidator {
        isAcceptable(s: string) {
            return s.length === 5 && numberRegexp.test(s);
        }
    }
}

我抛出的几乎相同的代码。

  1. 命名空间。
  2. 名称空间内的接口
  3. 类实现接口
  4. 类实现方法
// index.d.ts

declare namespace LA {
  export interface BelAir {
    populate(): undefined;
  }

  interface Burbank {

  }

  export class BelAirClass implements BelAir {
    populate() {  // Error is thrown here, 
      return undefined
    }
  }

}

// la.ts
import LA from './index';

const ba = new LA.BelAirClass();
const u: undefined = ba.populate();

console.log('[ba]', ba);
console.log('[u]', u);

// CLI
$ npm run tsc la.ts

index.d.ts:11:16 - error TS1183: An implementation cannot be declared in ambient contexts.

1 个答案:

答案 0 :(得分:1)

您的代码使用declare nampespace,它用于编写声明(通常用于现有JS代码)而没有任何实现。您的代码也位于d.ts文件中,该文件再次用于编写现有JS代码的声明。如果您删除declare并将代码移到.ts文件中,它将起作用。如果要export在另一个文件中命名空间,还请添加一个import

// index.ts
export namespace LA {
  export interface BelAir {
    populate(): undefined;
  }

  interface Burbank {

  }

  export class BelAirClass implements BelAir {
    populate() {  // Error is thrown here, 
      return undefined
    }
  }

}

// la.ts
import { LA } from './index';

const ba = new LA.BelAirClass();
const u: undefined = ba.populate();

console.log('[ba]', ba);
console.log('[u]', u);

此外,由于您正在使用模块(即exportimport语法),因此不建议使用namespace,这实际上是一种不好的做法。参见GH comment

  

可归结为:   如果您正在考虑使用名称空间进行代码组织:请勿。模块已包含该角色。   如果需要仅名称空间可以提供的功能:可以,但是请检查没有名称空间的概念(例如,具有类static或function属性或重新导出的模块)的表达能力是否相同。在同一个项目中混合名称空间和模块也是不好的风格-感觉很不好,因为传统意义上的名称空间的主要功能之一是跨文件范围合并,这种合并不会在模块之间发生(因为我说过,模块本身实际上是一个名称空间。

因此,带有模块的代码将是:

// index.ts


export interface BelAir {
  populate(): undefined;
}

interface Burbank {

}

export class BelAirClass implements BelAir {
  populate() {  // Error is thrown here, 
    return undefined
  }
}



// la.ts
import * as LA from './index';

const ba = new LA.BelAirClass();
const u: undefined = ba.populate();

console.log('[ba]', ba);
console.log('[u]', u);