【问题标题】:Typescript React: Union type for props does not display error when providing excess propertiesTypescript React:提供多余属性时,道具的联合类型不显示错误
【发布时间】:2018-10-12 02:31:58
【问题描述】:

我正在尝试为 React 组件的 props 使用联合类型

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 道具,有效道具会改变。然而,虽然没有出现在联合中的任何类型上的额外属性将是一个错误,但似乎出现在至少一个联合类型中但不属于基于判别属性的类型将不是错误。

我不确定为什么会这样。使用联合类型作为 react 组件的 props 是一种反模式吗?

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    当涉及联合时,问题与过多的属性检查有关。您可以阅读此答案here 来回答类似的问题。它的要点是联合的多余属性检查允许任何成员的任何键出现在对象上。我们可以通过引入额外的类型成员来解决这个问题,以确保具有多余属性的对象不会错误地与特定成员兼容:

    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?" />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-28
      • 1970-01-01
      • 2023-01-19
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 2021-05-11
      • 2021-04-03
      相关资源
      最近更新 更多