【问题标题】:typescript interface initialization打字稿接口初始化
【发布时间】:2014-05-01 16:31:38
【问题描述】:

我的打字稿水平是“绝对初学者”,但我有良好的 OOP 背景。我正在构建一个 with typescript,它引用了一个包含以下接口的外部 t.ds 库:

interface ISimpleObject {
    foo: string;
    bar?: any;
}

现在,如果我想调用具有 IRequestConfig 参数的方法,我该如何创建一个?我可以看到不同的选项:

  1. 创建一个简单的 ISimpleObject 实现。我不喜欢这种方法,因为它在我看来就像样板代码
  2. 不要初始化对象(我担心这会破坏某些东西......):

    var x :IsimpleObject; x.bar = 'xxx'; callMethod(x);

  3. 投一个pojo:

    var x :IsimpleObject = <IsimpleObject>{foo: 'yyy', bar:'xxx'};

    我也不喜欢这种方法,因为它不强制类型安全...

我想这是一个相当微不足道的问题,我错过了一些关于打字稿的微不足道的东西。

【问题讨论】:

    标签: oop typescript


    【解决方案1】:

    打字稿2:

    const simpleObject = {} as ISimpleObject;
    

    【讨论】:

    • 这有效吗?一些 ts-linting 规则对此提出警告:“禁止对对象文字进行类型断言,请改用类型注释”
    • 这对我有用 Angular 5.2.5/TypeScript 2.6.2 谢谢
    【解决方案2】:

    如果你有这样的界面:

    interface ISimpleObject {
        foo: string;
        bar?: any;
    }
    

    此接口仅用于编译时和代码提示/智能感知。接口用于提供一种严格且类型安全的方式,以一致的方式使用具有已定义签名的对象。

    如果您有使用上面定义的interface 的函数:

    function start(config: ISimpleObject):void {
    
    }
    

    如果对象没有ISimpleObject 接口的确切签名,TypeScript 编译将失败。

    调用函数start有多种有效技术:

    // matches the interface as there is a foo property
    start({foo: 'hello'});
    
    // Type assertion -- intellisense will "know" that this is an ISimpleObject
    // but it's not necessary as shown above to assert the type
    var x = <ISimpleObject> { foo: 'hello' }; 
    start(x);
    
    // the type was inferred by declaration of variable type
    var x : ISimpleObject = { foo: 'hello' };  
    start(x);
    
    // the signature matches ... intellisense won't treat the variable x
    // as anything but an object with a property of foo. 
    var x = { foo: 'hello' };
    start(x);    
    
    // and a class option:
    class Simple implements ISimpleObject {
        constructor (public foo: string, public bar?: any) {
           // automatically creates properties for foo and bar
        }
    }
    start(new Simple("hello"));
    

    任何时候签名不匹配,编译都会失败:

    // compile fail
    var bad = { foobar: 'bad' };
    start( bad );
    
    // compile fail
    var bad: ISimpleObject = { foobar: 'bad' };
    
    // and so on.
    

    没有“正确”的方法来做到这一点。这是风格选择的问题。如果它是一个被构造的对象(而不是直接作为参数传递),我通常会声明类型:

    var config: ISimpleObject = { foo: 'hello' };
    

    这样,代码完成/IntelliSense 将在我使用 config 变量的任何地方工作:

    config.bar = { extra: '2014' };
    

    TypeScript 中没有“强制转换”。它被称为类型断言,在此处描述的情况下不需要(我在上面提供了一个可以使用它的示例)。在这种情况下不需要声明变量 Type 然后使用断言(因为类型已经知道)。

    【讨论】:

    • TypeScript 2 中唯一有效的语法是const simpleObject = {} as ISimpleObject;,下面的@sdrevk 回答了。
    【解决方案3】:
    • 您不能创建接口的实例,因为 Typescript 不会将其“翻译”成 js。您可以检查创建的 js,您将看不到任何内容。编译错误、类型安全和智能感知很简单。

      interface IStackOverFlow
      {
         prop1 : string;
         prop2 : number;
      }
      
      public MyFunc(obj : IStackOverFlow)
      {
          // do stuff
      }
      
      var obj = {prop1: 'str', prop2: 3};
      MyFunc(obj); // ok
      
      var obj2 = {prop1: 'str'};
      MyFunc(obj); // error, you are missing prop2
      
      // getObj returns a "any" type but you can cast it to IStackOverFlow. 
      // This is just an example.
      var obj = <IStackOverFlow> getObj();
      

    【讨论】:

    • 这取决于您需要做什么。由于您不能“新建”一个界面,因此您只能转换 pocos 并让 typescript 编译器监视您正在做正确的事情..
    • pojos 的问题是编译器没有告诉我参数是否正确,所以如果我写fooo 而不是foo 我不会收到任何警告。我说的对吗?
    • 如果您没有正确使用“类型”,编译器会告诉您您不正确。我的示例显示,当您在 poco 中缺少强制属性时,编译器会告诉您。您可以使用可为空的类型来使属性成为可选的(类似于 prop2? : number 会告诉 ts 编译器 prop2 是一个数字,但作为对象中的属性不是强制性的)。
    猜你喜欢
    • 2018-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    • 2017-11-16
    相关资源
    最近更新 更多