【问题标题】:React: make typescript infer children type based on conditions in another componentReact:使打字稿根据另一个组件中的条件推断子类型
【发布时间】:2020-05-14 10:34:52
【问题描述】:

我想编写一个组件,该组件仅在某些给定的 prop 不为 null 时才呈现其子级(例如,在获取一些数据时呈现加载器,并在获取完成时使用实际数据进行更新)。 这很简单:

import React, { ReactElement, ReactNode, useState } from 'react'

type TState = {
    data: {
        text: string
    } | null
}

type NotNullProps = {
    children: ReactNode
    state: TState
}

const NotNull = ({ children, state }: NotNullProps) => {
    if (!state.data) {
      return null
    }

    return <>{children}</>
}

现在,如果我想以这种方式使用这个组件怎么办?

const Example = () => {
    const [state] = useState<TState>({ data: null })

    return (
        <NotNull state={state}>
            <div>{state.data.text}</div> // <--- "Object is possibly 'null'."
        </NotNull>
    )
}

Typescript 正确地表明 state.data 可以为空,因为它无法推断 NotNull 中发生的事情,但 state.data 永远不会为空,因为 NotNull 会检查它。
我知道这可以通过渲染道具解决,但它们给代码添加了一些混乱。那么,有没有办法输入NotNull,这样打字稿就不会抱怨/可以推断出正在发生的事情?

这是一个可以尝试的游乐场:https://tsplay.dev/zwORWq

(是的,我知道Suspense 和其他东西,但它与这个问题无关。我只想知道是否有办法以打字稿可以推断出值不为空的方式键入这个组件(同样,没有渲染道具))。

【问题讨论】:

    标签: reactjs typescript jsx


    【解决方案1】:

    您仍需检查state.data 是否为null,因为即使您的NotNull 组件阻止子组件渲染,您的代码仍将导致TypeError如果state.datanull,则使用您的用法,因为代码中的state.data.text 行在解释时将产生TypeError: Cannot read property 'text' of null,无论孩子是否呈现。我建议将这些行更改为:

    return (
        <NotNull state={state}>
            <div>{state.data && state.data.text}</div>
        </NotNull>
    )
    

    当然,这首先会否定NotNull 组件的需要,除了它还会阻止您的示例中的&lt;div&gt; 被呈现

    【讨论】:

    • 是的,这是之一可能的解决方案,但不是问题中提出的问题
    • 除非您以某种方式重组此代码,否则无法防止错误代码中发生错误。如果你愿意,你可以使用非空的! 断言符号,它向 TypeScript 发出信号,表明你确定数据不是null。但同样,在它 null 的情况下(因为再次阻止它呈现并不能阻止代码中可能的 null 属性访问),你的代码保证会出错
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 1970-01-01
    • 1970-01-01
    • 2018-08-12
    • 1970-01-01
    • 2018-06-09
    • 2019-05-03
    相关资源
    最近更新 更多