NodeJS 如何在React中使用Typescript循环两个接口Prop的联合

ddarikpa  于 11个月前  发布在  Node.js
关注(0)|答案(2)|浏览(189)

从下面的结构使用React 16.9.0Typescript ^16.9.20"

file A.ts:
export interface person{
  id: number || null,
  first_name: string,
  date_of_birth: string,
  some_unique_number: string,
}

file B.ts:
export interface member{
 group_name: string:
 first_name: string,
 pass_code: string,
 some_unique_number: string,
}

file C.tsx:
# import file A
# import file B

interface Props {
  result: Array<person | member>; 
}

let newResult: any[] = [];                       <=== I feel like `any[]` is wrong maybe

if (result) {
    newResult = results.map((result) => {
      return (
        <div className="something" key={item.some_unique_number}>
          {result.id}
          {result.first_name}
          {result.date_of_birth}
          {result.group_name}
          {result.pass_code}
        </div>
      );
    });
  }

字符串
我目前的解决方案产生了下面的错误:

Property 'id' does not exist on type 'person | member'.
  Property 'id' does not exist on type 'member'.  TS2339

    20 |         <div className="something" key={item.external_member_id}>
  > 21 |           {item.id}


基本上,我试图完成的是通过两个接口循环,并显示A和B的联合。
先谢谢你了。

mm9b1k5b

mm9b1k5b1#

让我们简化你的代码以便更好的理解。我们创建两个不同的接口A和B,并为每个接口添加一个项到results变量中。

interface A {
  name: string
  age: number
}

interface B {
  name: string
  country: string
}

results: Array<A | B> = [
 {name: "Mike", age: 30},
 {name: "John", country: "DE"}
]

字符串
让我们来看看这两段代码,它们试图呈现结果项。

results.map((item) => 
  <div>{item.name}</div> // works as expected
)

results.map((item) => 
  <div>{item.name}-{item.age}</div> // you will get a typescript error
)


在第一个results.map中,我们只使用了属性name。如果你尝试运行这段代码,它会工作,因为属性nameinterfacesAB中都有。对于第二个result.map,你会得到一个Typescript Error,属性age在接口B中不存在。我们如何解决这个问题?
解决方案叫做类型保护!类型保护确保您的项目具有属性或接口A或B。

results.map((item) => {
  return (
    <div>{result.name}</div> // both interfaces have this property
    <div>{"age" in result ? result.age : ""}</div> // ensure the item has the property age 
    <div>{"country" in result ? result.country : ""}</div> // ensure item has the property country
  )
})


你也可以使用函数来识别哪个接口是项目。当你的接口有很多不同的属性,而你不想检查每个属性时,它会使代码更具可读性。

const isA = (item: A | B): item is A // here you tell Typescript that the function parameter item is of interface A in case this function returns true {
  return 'age' in A; // check properties which are unique - in this case the interface A has a property age which interface B does not have
}


有了这个类型保护函数,

results.map((item) => {
  if (isA(item)){
    return (
       <div>{item.name}</div>
       <div>{item.age}</div>
    )
  }

  return (
     <div>{item.name}</div>
     <div>{item.country}</div>
  )
})


现在,typescript知道在if块中,我们使用接口A处理所有项,在此代码块之后,我们使用接口B处理项,因为results中只有这两个接口。
newResults的类型从any[]切换为ReactNode[]

vq8itlhq

vq8itlhq2#

https://medium.com/@martin_hotell/interface-vs-type-alias-in-typescript-2-7-2a8f1777af4c
您可以多次定义同一个接口,其定义将合并为一个:


的数据
不知道这是否有效,但如果我们用你的例子创造性:

// file A.ts
export interface person{
  id: number || null,
  first_name: string,
  date_of_birth: string,
  some_unique_number: string,
}

// file B.ts:
export interface member{
 group_name: string:
 first_name: string,
 pass_code: string,
 some_unique_number: string,
}

export interface peopleOrMember extends member
export interface peopleOrMember extends person

字符串
我希望这对你有用,如果它仍然不起作用,也许它是在该介质链接的某个地方.我复制了我提到的其他stackoverflow问题的链接.

相关问题