【问题标题】:Typescript with multiple types, how to determine which type has certain props具有多种类型的打字稿,如何确定哪种类型具有某些道具
【发布时间】:2021-11-15 09:47:48
【问题描述】:

假设我有 3 种类型。类型A、类型B和类型C

typeA 有 name 属性,而 typeB 和 typeC 没有

当我用类似的代码渲染它时;

interface propTypes {
 post: typeA | typeB | typeC
}

..... some react code ....
return( 
{post?.name && component})

但它返回错误:“类型'typeA| typeB | typeC上不存在属性'name'

我尝试 post instanceof typeA 但它返回错误 'typeA' 仅指一种类型,但在此处用作值。

【问题讨论】:

  • {post && 'name' in post && component}) 有效吗?
  • 天哪,你真是个救世主!一直在寻找几个小时。谢啦。您可以在下面添加您的答案,以便可能遇到相同问题的其他人可以看到如何解决此问题?
  • 已经有答案提到了这个解决方案,所以可以接受????

标签: reactjs typescript


【解决方案1】:

考虑这个例子:

type typeA = {
  name: string
}

type typeB = {
  surname: string
}

type typeC = {
  age: number
}

type post = typeA | typeB | typeC

interface propTypes {
  post: post
}

const App = ({ post }: propTypes) => {
  post // no autocomplete

  return null
}

post. 之后没有自动补全,因为你没有任何共同的道具。

docs

如果我们有一个联合类型的值,我们只能访问联合中所有类型共有的成员。

为了让它工作,你应该定义一个typeguard

const isTypeA = (props: unknown): props is typeA => Object.prototype.hasOwnProperty.call(props, 'name')

const App = ({ post }: propTypes) => {
  if (isTypeA(post)) {
    post.name // string
  }

  return null
}

或者,您可以使用in 运算符,它与联合非常有效:

const App = ({ post }: propTypes) => {
  if ('name' in post) {
    post.name // string
  }

  return null
}

或者你可以使用StrictUnion 输入:

type typeA = {
  name: string
}

type typeB = {
  surname: string
}

type typeC = {
  age: number
}

// credits goes to https://stackoverflow.com/questions/65805600/type-union-not-checking-for-excess-properties#answer-65805753
type UnionKeys<T> = T extends T ? keyof T : never;
type StrictUnionHelper<T, TAll> =
  T extends any
  ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;

type StrictUnion<T> = StrictUnionHelper<T, T>

type Post = StrictUnion<typeA | typeB | typeC>


interface propTypes {
  post: Post
}


const App = ({ post }: propTypes) => {
  if (post.name) {
    post.name // string
  }

  return null
}

Playground


'in' 运算符为我工作 请记住,它有自己的缺点:

type typeA = {
  name?: string
}

interface propTypes {
  post: typeA
}


const App = ({ post }: propTypes) => {
  if ('name' in post) {
    post.name.charAt // error
  }

  return null
}

它与联合完全兼容,但不适用于可选属性。

【讨论】:

  • 'in' 运算符为我工作。谢谢
  • @BonAndreOpina 当然,对缺点进行了更新
猜你喜欢
  • 2021-01-24
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
相关资源
最近更新 更多