在 React jsx 中将 props 作为泛型传递
Passing props in React jsx as generics
在我的 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 中 return SharedComponent 具有 InterfaceA 的通用类型和 Type 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) => data.name)
它抛出一个错误,说T没有名字的成员。所以我想我在这里传递的泛型不工作,因为作为泛型传递的 InterfaceA 与任何其他 InterfaceB 和 InterfaceC 一样具有成员“名称”。我做错了什么?
除非您通知它,否则 TypeScript 对函数内部的泛型一无所知。您需要从具有您在函数内部使用的属性的类型扩展泛型 T
。考虑这个例子:
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
}
}
更多,基于你问题中的代码:
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>
);
在我的 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 中 return SharedComponent 具有 InterfaceA 的通用类型和 Type 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) => data.name)
它抛出一个错误,说T没有名字的成员。所以我想我在这里传递的泛型不工作,因为作为泛型传递的 InterfaceA 与任何其他 InterfaceB 和 InterfaceC 一样具有成员“名称”。我做错了什么?
除非您通知它,否则 TypeScript 对函数内部的泛型一无所知。您需要从具有您在函数内部使用的属性的类型扩展泛型 T
。考虑这个例子:
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
}
}
更多,基于你问题中的代码:
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>
);