在角度1.5中绑定组件函数时,如何利用打字稿?

时间:2016-06-30 13:43:43

标签: angularjs typescript

我在跟随this best practices guide时尝试学习打字稿,但我觉得我在这里错过了一些东西。

这是一个使用打字稿编写的工作代码。让我困扰的是,我不觉得我们真的在这里利用打字稿。如果有人在哪里更改函数的签名,那么编译器就不会注意到它。

让我解释一下:

首先让我们来定义一个"

;

// thing.interface.ts
export interface IThing {
  name: string,
  id: number,
}

某些组件是一系列事物:

// listOfThings.component.ts
import ListOfThingCtrl from './listOfThings.controller.ts'
const listOfThings = {
  bindings: {
    things: '<',
  },
  controller: ListOfThingCtrl,
  template: `
  <p> list of things: <p>
  <ul>
    <li ng-repeat="thing in $ctrl.things">
      <thing thing="thing" on-delete="$ctrl.deleteThing($event)"></thing>
    </li>
  </ul>
  `,
}

我们有一个thing组件:

import ThingCtrl from './thing.controller.ts'

const thing = {
  bindings: {
    onDelete: '&',
    thing: '<',
  },
  controller: ThingCtrl,
  template: `
  <p>
    thing: {{$ctrl.thing.name}}
    <a ng-click='$ctrl.deleteThing()' >
      Delete me
    </a>
  </p>
  `,
}

这么好。

现在让我们定义控制器:

//listOfThings.controller.js
import {IThing} from './thing.interface.ts'

export default class ListOfThingCtrl {
  private things: Array<IThing>

  public deleteThing (thing: IThing): void {
    const i = this.things.map(t => t.id).indexOf(thing.id)
    if (i > -1) {
      this.things.splice(i, 1)
    }
  }
}


// thing.controller.js
import {IThing} from './thing.interface.ts'

export default class ThingCtrl {
  private thing: IThing

  // This line looks dangerous to me : this should be imported, not declared !
  private onDelete: (e: {$event: IThing}) => void // What now if the bounded function were to change ?

  public deleteThing (): void {
    this.onDelete({$event: this.thing})
  }
}

此代码&#34;工作&#34; :它加载,编译没有抱怨,点击一些&#34;删除我&#34;实际上会删除一个&#34;&#34;来自控制器列表&#34;事物&#34;

现在困扰我的是:在这段代码中,我们向onDelete组件注入thing函数,但我们从未注入其实际签名。

如果有人要更改deleteThing功能;让&#39;说deleteThing(thingId: number)而不是deleteThing(thing: IThing)。然后不再有效,但编译器编译得很好

我觉得使用打字稿的重点是避免这种情况:deleteThing的签名已经改变,但是onDelete仍然会用旧参数调用它而不知道它将在运行时失败。

然而,我对打字稿很新,所以我可能在这里遗漏了一些重要的东西。

是否有允许通过角度组件传递函数签名的最佳实践?

感谢阅读!

1 个答案:

答案 0 :(得分:0)

我想出了一些令我满意的事情:

首先,让我们对ListOfThings组件模板进行一些修改:

<thing thing="thing" on-delete="$ctrl.deleteThing({$event})"></thing>

(而不是deleteThing($event)),以便onDeletedeleteThing具有完全相同的签名。

thing.interface.js中声明一个函数接口:

export interface IDeleteThing {
      (e: {$event: {thing: IThing}}): void
    }

现在两个控制器都可以导入界面并使用它:

// listOfThings.controller.ts
import {IThing, IDeleteThing} from './thing.interface.ts'

export default class ListOfThingCtrl {
  private things: Array<IThing>

  public deleteThing: IDeleteThing = ({$event}) => {
    const i = this.things.map(t => t.id).indexOf($event.thing.id)
    if (i > -1) {
      this.things.splice(i, 1)
    }
  }
}

// thing.controller.ts
import {IThing, IDeleteThing} from './thing.interface.ts'

export default class ThingCtrl {
  private thing: IThing
  private onDelete: IDeleteThing

  public deleteThing (): void {
    this.onDelete({$event: {thing: this.thing}})
  }
}

由于签名现在在共享模块中定义,编译器现在将检测到两个控制器之间的任何不一致\ o /