繁体   English   中英

React:TypeScript generics,自动切换参数类型来自 function(用作道具)

[英]React: TypeScript generics, auto switch parameter-type from function (function as props)

我想实现以下(在 React/TypeScript (.tsx) 中)

Main.tsx (编辑: botCommands是一个数组,其中可以包含多个对象(使用commandbotResponse()

function Main() {
  return (
    <TestComponent
      botVariables={{
        tasks: [],
        groups: []
      }}
      botCommands={[
        {
          command: "-help",
          botResponse(botVariables) {
            return botVariables.tasks[0]
          }
        }
      ]}
    />
  );
}

测试组件.tsx

interface BotCommand {
  command: string;
  botResponse(botVariables: any): string;
}

interface TestComponentProps {
  botVariables: any;
  botCommands: BotCommand[];
}

export default function TestComponent(props: TestComponentProps) {
  return (
    // magic
  );
}

Main.tsx我希望在 function botResponse()中自动调整类型(当前为any )。 这样会自动将botVariables的内容作为类型。

简单地说,如果我在Main.tsx botResponse() function “botVariables”中写入 Main.tsx。 IDE 可以向我建议tasksgroups botVariables中的数据可以更改,因此您不能只在TestComponent.tsx文件中创建接口。

我尝试使用 typescript generics 但不幸失败了。 感谢帮助!

如果我正确理解您的要求, botVariables可以是任何东西,但我们提供给TestComponentbotVariablesbotCommands需要相互匹配。 即botCommands中botResponse function的botCommandsbotVariables prop的类型相同。

为此,我们将BotCommand接口设为通用接口,其中类型T表示botResponse变量的类型。

interface BotCommand<T> {
  command: string;
  botResponse(botVariables: T): string;
}

我们的TestComponentProps也是通用的,我们将相同的T应用于botVariablesbotCommands

interface TestComponentProps<T> {
  botVariables: T;
  botCommands: BotCommand<T>[];
}

这意味着该组件也是通用的。

export default function TestComponent<T>(props: TestComponentProps<T>) {...}

从传递的变量创建响应没有问题,因为两个props共享相同的T

export default function TestComponent<T>({ botVariables, botCommands }: TestComponentProps<T>) {
    return (
        <div>
            <h1>Bot Output</h1>
            {botCommands.map(command => (
                <div>
                    <div>Bot recieved command {command.command}</div>
                    <div>Bot responded {command.botResponse(botVariables)}</div>
                </div>
            ))}
        </div>
    );
}

使用TestComponent时不需要显式声明泛型T ,因为它可以从botVariables中推断出来。 如果botCommands不匹配,typescript 会抱怨。

在这个例子中:

function Main() {
  return (
    <TestComponent
      botVariables={{
        tasks: ["first"],
        groups: ["something"]
      }}
      botCommands={[{
        command: "-help",
        botResponse(botVariables) {
          return botVariables.tasks[0]
        }
      }]}
    />
  );
}

botResponse function 的推断签名是完整且正确的:

(method) BotCommand<{ tasks: string[]; groups: string[]; }>.botResponse(botVariables: {
    tasks: string[];
    groups: string[];
}): string

为了得到正确的推断,我不得不使用["first"]而不是空数组,因为空的 arrays 被输入为never[]但我们想要string[] 您可以使用空数组,但必须显式设置它的类型。

游乐场链接

欢迎来到 StackOverflow 社区。

Typescript 无法自动检测您的参数类型。

无论如何,您可以选择使用联合类型通用类型

如果变量是一组有限的类型,您可以使用联合类型。

interface MyObject {
    tasks: string[]
}

interface BotCommand {
  command: string;
  botResponse: (botVariables: string | number | MyObject) => string;
}

泛型类型示例

interface BotCommand {
  command: string;
  botResponse: <T extends unknown>(botVariables: T) => string;
}

在这两种情况下,您都需要在使用 object 之前“识别”它的当前类型。 为此,您可以使用Typeguard

function isMyObject(x: unknown): x is MyObject {
  return (x as MyObject).tasks !== undefined
}

有关更多信息,请查看这个游乐场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM