2016-08-10 47 views
3

我来自C#背景下的Typescript。在Typescript中,界面是否有用(从结构上讲)?

在C#中,如果我有一个名为BillingService的类,它具有调用结算服务(可以进行支付,给予帐户余额等)的方法,那么对于需要调用该类的代码部分,我会设置一个单独的程序集,其中定义了一个IBillingService

我的代码的其余部分将使用依赖注入来获得IBillingService,并且永远不会引用实际实现BillingService的程序集。这促进了单元测试,松散耦合和数据隐藏的其他一些好处。

当我第一次使用TypeScript时,我一直这样做。但现在我想知道是否有任何实际的好处。明智地使用公共和私人似乎就足够了。

在Typescript中没有单独的程序集。依赖注入可以注入实际的类,就好像它已经实现了一个接口(至少Aurelia的依赖注入可以)。无论如何,JavaScript单元测试框架似乎都被Interfaces困惑。

所以,这里是我的问题:

对于我上面列出的情况下,是有一个用例的打字稿接口?如果是这样,它是什么?

+0

接口对于“良好设计”和良好合同仍然很重要;如果使用得当,它们会在其余的程序构建过程中形成一个可靠的参考蓝图。他们还允许多份合同的清洁组合。然而,Typescript的[类型兼容性](https://www.typescriptlang.org/docs/handbook/type-compatibility.html)会将'必要使用'转移到一些.. – user2864740

回答

2

与其他一些OO语言一样,在打字稿中也不可能有多重继承,但可以实现多个接口,这是接口适合的一种用例。

的另一个原因是,如果你想在不同的命名空间/模块传播不同的实现,但你希望它们都实现特定的一套方法:

namespace callbacks { 
    export interface Callback<T> { 
     getName(): string; 
     execute(): T; 
    } 
} 

namespace mynamespace1 { 
    export class Callback implements callbacks.Callback<string> { 
     public getName(): string { 
      return "mynamespace1.Callback"; 
     } 

     public execute(): string { 
      return "executed"; 
     } 
    } 
} 

namespace mynamespace2 { 
    export class Callback implements callbacks.Callback<boolean> { 
     public getName(): string { 
      return "mynamespace2.Callback"; 
     } 

     public execute(): boolean { 
      return true; 
     } 
    } 
} 

但最好的理由(在我看来)是它可以让你躲闭包内的实现类,以便没有人只能通过工厂函数或一些行动直接,但创建它们:

namespace logging { 
    const httpLoggingEndpoint: URL = new URL(...); 
    const fileLoggingFilePath: string = "LOG_FILE_PATH"; 

    export enum LoggerType { 
     Console, 
     Http, 
     File 
    } 

    export interface Logger { 
     log(message: string): void; 
    } 

    export function getLogger(type: LoggerType): Logger { 
     switch (type) { 
      case LoggerType.Console: 
       return new ConsoleLogger(); 

      case LoggerType.Http: 
       return new HttpLogger(); 

      case LoggerType.File: 
       return new FileLogger(); 
     } 
    } 

    class ConsoleLogger implements Logger { 
     public log(message: string): void { 
      console.log(message); 
     } 
    } 

    class HttpLogger implements Logger { 
     public log(message: string): void { 
      // make a request to httpLogingEndpoint 
     } 
    } 

    class FileLogger implements Logger { 
     public log(message: string): void { 
      // log message to the file in fileLoggingFilePath 
     } 
    } 
} 

这样,没有人可以直接实例化一个记录器,因为没有实际的类都是前移植。

还有一点就这一主题是在打字稿类可以作为接口进行处理:

class Logger { 
    public log(message: string) { 
     console.log(message); 
    } 
} 

class HttpLogger implements Logger { 
    public log(message: string) { 
     // log using an http request 
    } 
} 

这是在实践中用于mixins例如,所以我的前两个方案可以用类作为完成好吧,虽然我的最后一个例子不能和类一样好,因为那样你可以实例化基类,并绕过不能直接调用不同构造函数的“安全机制”。

相关问题