当前位置: 首页 > 面试题库 >

Typescript React:提供多余属性时,道具的联合类型不显示错误

戚鸿福
2023-03-14
问题内容

我正在尝试将Union类型用于React组件的道具

type Props =
  | {
      type: "string"
      value: string
    }
  | {
      type: "number"
      value: number
    }
  | {
      type: "none"
    }

class DynamicProps extends React.Component<Props> {
  render() {
    return null
  }
}

// Ok
const string_jsx = <DynamicProps type="string" value="hello" />

// Error as expected, value should be a string
const string_jsx_bad = <DynamicProps type="string" value={5} />

// Ok
const number_jsx = <DynamicProps type="number" value={5} />

// Error as expcted value should be a number
const number_jsx_bad = <DynamicProps type="number" value="hello" />

// Error as expected, invalid isn't a property on any of the unioned types
const extra = <DynamicProps type="string" value="extra" invalid="what" />

// No error? There should be no value when type="none"
const none_jsx = <DynamicProps type="none" value="This should be an error?" />

// Ok, seems like value has become optional
const none2_jsx = <DynamicProps type="none" />

// Error as expected, value is not present. Value doesn't seem to be made optional all the time
const required = <DynamicProps type="string" />

似乎部分起作用,因为type有效道具会根据道具而改变。但是,虽然没有出现在联合中的任何类型上的额外属性将是一个错误,但似乎出现在至少一个联合类型中但不基于判别属性的类型将不是错误。

我不确定为什么会这样。使用联合类型作为反应组件的道具是否是反模式?


问题答案:

当涉及工会时,问题与多余的财产检查有关。您可以在此处阅读类似问题的答案。其要旨是,对联合的多余属性检查允许对象上存在任何成员的任何键。我们可以通过引入额外的类型的成员来避免这种情况,即永远不要确保具有过多属性的对象不会与特定成员错误地兼容:

type Props =
| {
    type: "string"
    value: string
    }
| {
    type: "number"
    value: number
    }
| {
    type: "none"
    }

type UnionKeys<T> = T extends any ? 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>

class DynamicProps extends React.Component<StrictUnion<Props>> {
    render() {
        return null
    }
}
// error now
const none_jsx = <DynamicProps type="none" value="This should be an error?" />


 类似资料: