Typescript 接口中禁止的属性

Prohibited attributes in a Typescript Interface

我要创建一个 TypeScript 接口,它不仅要求存在特定属性,而且禁止不属于定义一部分的属性。这是一个例子:

  export interface IComponentDirective {
    scope : any;
    templateUrl : string;
  };

  var ddo : IComponentDirective = {
    scope: {
      dt: '='
    },
    templateUrl: 'directives.datepicker',
    controller: function() {
      console.log('hello world');
    }
  };

即使接口中未定义 controllerddo 赋值也不会引发错误。做一些研究,这看起来可能是设计的:

Notice that our object actually has more properties than this, but the compiler only checks to that at least the ones required are present and match the types required.

http://www.typescriptlang.org/Handbook#interfaces

但是请注意,在我将 ddo 声明为 IComponentDirective 之后,如果我尝试以下操作:

ddo.transclude = false;

转译器会抱怨:

2339 Property 'transclude' does not exist on type 'IComponentDirective'.

有什么方法可以执行更严格的合同吗?

简而言之(但取决于您对 "tighter" 的定义)您不能限制超出此范围的事情。

界面是一个合同,上面写着"if these members are not present, you aren't one of these"。如果您的对象恰好有其他成员,那很好;当您使用界面时,它们对您来说是不可见的。

例如(根据您的代码),当您键入 ddo. 时,它只会建议接口上的成员,因为您已告诉编译器使用接口类型。

您不能使用接口来阻止定义成员。我想不出有任何语言可以做到这一点。例如,在 C# 中,您可以实现比接口要求您实现的更多的成员,但是当您使用接口类型时,其他成员将不可用。

动态添加属性

关于为什么 ddo.tranclude = false; 生成警告的问题有点不同。这与接口无关 - 它会在没有接口时执行:

  var ddo = {
    scope: {
      dt: '='
    },
    templateUrl: 'directives.datepicker',
    controller: function() {
      console.log('hello world');
    }
  };

  ddo.transclude = false; // Nope

原因是……这就是TypeScript的意义所在!它警告您可能输入了错误的 transclude。也许您的意思是 templateUrl 存在。如果 TypeScript 没有就此类问题向您发出警告,它会让您在代码中引入印刷错误。

所以 TypeScript 将为您创建的任何对象生成一个类型,然后强制执行该结构,除非您另有说明。

如果你想 "sometimes be a transclude member" 你可以做到:

interface SometimesTransclude {
    scope: { dt: string};
    templateUrl: string;
    controller: () => void;
    transclude?: boolean;
}

  var ddo: SometimesTransclude = {
    scope: {
      dt: '='
    },
    templateUrl: 'directives.datepicker',
    controller: function() {
      console.log('hello world');
    }
  };

  ddo.transclude = false;

或者您可以使用以下方法直接绕过编译器(风险自负):

ddo['transclude'] = false;