使用 TypeScript 时,在 Node.js 客户端库中扩展 "conv" 实例以在 Google v2 上执行操作

Extend "conv" instance in Node.js Client Library for Actions on Google v2 when using TypeScript

Google Node.js 客户端库 v2 上的 Actions 中有一个 middleware 允许添加conv 实例的属性或助手 类。官方版本 1 迁移指南中的示例:

const { dialogflow } = require('actions-on-google');

class Helper {
  constructor(conv) {
    this.conv = conv;
  }

  func1() {
    this.conv.ask(`What's up?`);
  }
}

const app = dialogflow()
  .middleware(conv => {
    conv.helper = new Helper(conv);
  });

app.intent('Default Welcome Intent', conv => {
  conv.helper.func1();
});

这可能适用于普通 JavaScript。但是如果使用TypeScript呢?

如果代码是用 Typescript 编写的,TSC 会抱怨行 conv.helper = new Helper(conv);conv.helper.func1();:

[ts] Property 'helper' does not exist on type 'DialogflowConversation<{}, {}, Contexts>'.

也许我可以将其重写为 (<any>conv).helper,但这很难看。有人知道(更好的)解决方案吗?

dialogflow 应用程序创建函数重载了泛型类型参数,允许您覆盖通过 Intent 处理程序发送的对话类型。

您只需创建一个扩展适当对话类型的类型。为了保持所有类型的安全性要复杂得多,但它是可行的。

因此,您在 TypeScript 中共享的最安全和通用实现中的代码段将是:

import {
  dialogflow,
  DialogflowConversation,
  DialogflowMiddleware,
  Contexts,
} from 'actions-on-google';

// an interface with the extensions to the Conversation type
interface HelperConversation<
  TData = {},
  TUserStorage = {},
  TContexts extends Contexts = {},
> extends DialogflowConversation<TData, TUserStorage, TContexts> {
  helper: Helper<TData, TUserStorage, TContexts>;
}

// the helper class now passing generic type parameters from the Conversation type
class Helper<TData, TUserStorage, TContexts extends Contexts> {
  constructor(public conv: DialogflowConversation<TData, TUserStorage, TContexts>) {}

  func1() {
    this.conv.ask(`What's up?`);
  }
}

// to keep type security in the middleware, it needs to be functional and of the DialogflowMiddleware type
const middleware: DialogflowMiddleware<HelperConversation> =
  conv => Object.assign(conv, { helper: new Helper(conv) })

// pass the extended Conversation interface into the `dialogflow` function
const app = dialogflow<HelperConversation>()
  .middleware(middleware);

app.intent('Default Welcome Intent', conv => {
  // now conv is of the type `HelperConversation`
  conv.helper.func1();
});

根据您希望 TypeScript 中间件的方式 secure/generic,您可以使用基本对象类型摆脱大量额外的通用参数,从而减少大量代码。

您还可以查看 alpha 期间共享的 TypeScript 代码片段,以了解 TypeScript 与库的更详细用法: