React: TypeScript泛型,从函数(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]
}
}
]}
/>
);
}

TestComponent.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我想在功能botResponse()类型(目前any)是自动调整。从而自动将botVariables的内容作为类型。

简单地说,如果我在Main.tsx中写入botResponse()函数"botVariables."tasksgroups可以由IDE推荐给我。botVariables中的数据可以更改,因此您不能仅在TestComponent.tsx文件中创建接口。

我尝试使用typescript泛型,但不幸失败了。谢谢你的帮助!

如果我正确理解您的要求,botVariables可以是任何东西,但是我们提供给TestComponentbotVariablesbotCommands需要相互匹配。也就是说,botCommandsbotResponse函数的参数与botVariablesprop的类型相同。

为了做到这一点,我们使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,因为它可以从botVariablesprop中推断出来。如果botCommands不匹配,typescript会报错。

在这个例子中:

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

botResponse函数的推断签名是完整和正确的:

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

为了得到正确的推断,我不得不使用["first"]而不是空数组,因为空数组类型为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;
}

在这两种情况下你都需要"识别"在使用对象之前,对象的当前类型。要做到这一点,你可以使用Typeguard。

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

更多信息请看这个游乐场

最新更新