具有多种类型的 Typescript,如何确定哪种类型具有某些 props

Bon*_*ina 1 typescript reactjs

可以说我有 3 种类型。A 型、B 型和 C 型

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

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

interface propTypes {
 post: typeA | typeB | typeC
}

..... some react code ....
return( 
{post?.name && component})
Run Code Online (Sandbox Code Playgroud)

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

我尝试 post instanceof typeA 但它返回错误“typeA”仅引用类型,但在此处用作值。

cap*_*ian 8

考虑这个例子:

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
}
Run Code Online (Sandbox Code Playgroud)

之后不会自动完成,post.因为您没有任何通用道具。

查看文档

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

为了使其工作,您应该定义一个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
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用in运算符,它与联合配合得非常好:

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

  return null
}
Run Code Online (Sandbox Code Playgroud)

或者您可以使用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
}

Run Code Online (Sandbox Code Playgroud)

操场


“in”运算符对我有用请记住它有自己的缺点:

type typeA = {
  name?: string
}

interface propTypes {
  post: typeA
}


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

  return null
}
Run Code Online (Sandbox Code Playgroud)

它与联合一起工作得很好,但与可选属性一起工作得不好。