将 React jsx 中的 props 作为泛型传递

Posted

技术标签:

【中文标题】将 React jsx 中的 props 作为泛型传递【英文标题】:Passing props in React jsx as generics 【发布时间】:2022-01-17 16:40:27 【问题描述】:

在我的 react 应用程序中,我想将特定接口作为泛型传递给非特定组件。

例如我有三个特定的接口

SpecificInterfaces.jsx
export interface InterfaceA 
   name: string
   age: number
   ...


export interface InterfaceB 
    name: string
    movies: string[]
    count: number
    ...


export interface InterfaceC 
    name: string
    somestuff: someType

对于每个接口,我都有一个特定的组件 ComponentA、ComponentB 和 ComponentC。 这些组件需要在共享组件ComponentShared中使用。

现在,例如,我希望在我的 ComponentA 中返回 SharedComponent,其具有 InterfaceA 的通用类型和 InterfaceA 类型的道具,如下所示:

ComponentA.jsx
export interface Props<T> 
    importData: T[]
    ... some props... 


const props: Props<InterfaceA> = 
importData: importData //This is from Interface Type InterfaceA
... someProps ...

  return (
        <React.Fragment>
            <SharedComponent<InterfaceA> ...props />
        </React.Fragment>
    )

在我的 sharedComponent 中,我想像这样访问特定传递的泛型类型:

SharedComponent.jsx
const SharedComponent= <T,>(
   importData,
   ...the passed Props
: Props<T>): JSX.Element => 
importData.map((data: T) =>
    data.name) 

importData.map((data:T) =&gt; data.name) 它会抛出一个错误,说 T 没有 name 的成员。所以我想我在这里传入的泛型不能正常工作,因为作为泛型传入的 InterfaceA 具有成员“名称”,就像任何其他 InterfaceB 和 InterfaceC 一样。我做错了什么?

【问题讨论】:

【参考方案1】:

TypeScript 对函数内部的泛型一无所知,除非您通知它。您需要从具有您在函数内部使用的属性的类型扩展您的通用 T。考虑这个例子:

TS Playground

function logNamesBroken <T>(objects: T[]): void 
  for (const obj of objects) 
    console.log(obj.name);
/*                  ^^^^
Property 'name' does not exist on type 'T'.(2339) */
  


type BaseObject = 
  name: string;
;

function logNames <T extends BaseObject>(objects: T[]): void 
  for (const obj of objects) 
    console.log(obj.name); // ok now
  


更多,根据您问题中的代码:

TS Playground

import default as React from 'react';

interface BaseItem 
  name: string;


interface InterfaceA extends BaseItem 
  age: number;


interface Props<T extends BaseItem> 
  importData: T[];


const SharedComponent = <T extends BaseItem>(
  importData,
: Props<T>): React.ReactElement => 
  return (
    <ul>
      
        importData.map((data, index) => (
          <li key=`$index-$data.name`>data.name</li>
        ))
      
    </ul>
  );
;

const importData: InterfaceA[] = [name: 'a', age: 1, name: 'b', age: 2];

const props: Props<InterfaceA> = 
  importData,
;

const AnotherComponent = (): React.ReactElement => (
  <React.Fragment>
    <SharedComponent ...props />
  </React.Fragment>
);

【讨论】:

感谢您的快速回复!我是否理解正确,那么我想要实现的目标根本不可能?因为我有几个接口或者类型,应该和SharedComponent兼容。这些接口或类型也将在不久的将来扩展和/或由新类型补充...... @Alex 老实说,我很难理解您问题中的代码,因为它不是有效的语法:有未注释的 cmets 与代码混合,return 函数外的语句等. 我很难弄清楚您的真正意图是什么,但是,我根据收集到的信息用另一个示例更新了我的答案。 您的新解决方案似乎符合我的要求!我需要验证一下,但到目前为止它看起来很棒。太感谢了!是的,我知道,老实说,我不确定我应该做什么,我刚刚得到了“使组件与泛型一起工作”的任务......:D

以上是关于将 React jsx 中的 props 作为泛型传递的主要内容,如果未能解决你的问题,请参考以下文章

11. react 组合与继承

在 JSX | React 如何将 prop 传递给按钮状态,以便按钮状态可以加载新页面?

`[react/jsx-max-props-per-line]` eslint 规则,复合设置

如何将可变数量的道具传递给 React 中的 JSX 标签

react属性展开...props

使用 VSCode 更漂亮的 react/jsx-max-props-per-line 格式