TS系列(1): React中能否使子组件实现“类型安全”?

本篇是**「一起学习** TypeScript **」**系列的开篇之作,接下来笔者将持续深耕,不定时更新一系列精彩纷呈的TypeScript文章,旨在解答使用TypeScript过程中的各种疑难杂症,一起探索TS的无穷魅力!

一、引言

在进入正题之前,我们先来明确一个概念,什么是"类型安全"(Type Safety)?

看看ChatGPT怎么回答这个问题:

"Type safety"(类型安全)是指编程语言的一个特性,它确保在编译时或运行时,程序中的类型匹配是正确的。这意味着程序员不能将一个类型不匹配的值赋给一个变量,或者将一个类型不匹配的参数传递给一个函数。这可以避免许多常见的编程错误,例如将字符串传递给一个期望整数的函数,或者将一个浮点数赋给一个期望布尔值的变量。类型安全还可以提高程序的可读性和可维护性,因为它使得程序员更容易理解代码中的数据类型和操作。

一句话总结下:类型安全是指确保数据在使用时保持预期的类型。

二、可以实现子组件 "类型安全"么?

如果你已经使用过TS和JSX一段时间,也许你会面临一种情形:想要将一个组件的子组件限制为某种特定的类型。

那么,这个述求能否实现呢?🤔

先来看一个简单的例子🌰:现在有一个Select组件,它的子组件为Option。如果想确保Option是唯一能够传递给Select的组件👇🏻

javascript 复制代码
//✅
<Select>
  <Option value="1">One</Option>
  <Option value="2">Two</Option>
  <Option value="3">Three</Option>
</Select>

//❌
<Select>
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</Select>

看起来似乎有很多选择:使用ReactElement,或者ReactNode,或者ReactChild?

实际上,这些类型都没有任何效果,你不能告诉 TypeScript"只使用指定类型的组件作为子组件"!

组件总是JSX.Element类型

根本原因在于 TypeScript 解释 JSX 的方式:不管是什么组件,组件里面有什么 props , TS 看到一个JSX语句时,总是把它定义为一个 JSX.Element !

当我们想让Select组件仅接收Option组件作为参数时,我们也许会这么写:

ini 复制代码
type SelectProps = {
   children: ReactElement<OptionProps>[];
}

但是,实际上,Option组件还是会返回一个JSX.Element !🤯

尝试手动覆盖返回类型

那么,如果我们使用TS的as语法覆盖组件的返回类型呢?

下面的代码👇🏻中,你会发现element的类型依然是React.JSX.Element!😒

不过,如果你手动调用Option() ,确实会达到想要的效果:

这种手动调用的方式其实是绕过了JSX解释的机制,所以TS能够理解Option要返回的是我们指定的字符串。

但是需要注意的是,在React中手动调用Option()是一个糟糕的主意------它会打破React对代码所做的各种假设,将会导致一些不可预计的错误。-_-||

三、结论

综上所述: 在 TypeScript 中不可能将 React 组件的子组件限制为某种类型 。

但是,这里仍然有一件事情需要思考:你是真的想要限制子组件类型吗?😏

React的魔力本质上是在于你可以按照你喜欢的任何方式组合你的组件。但是如果你限制了子组件为一种固定的类型,你将打破这种可组合性(composability) !

一种更好的方式是:也许你可以通过使用对子组件的props进行限制来实现你的目的👇🏻

ini 复制代码
<Select
  options={[
    { value: "1", label: "One" },
    { value: "2", label: "Two" },
    { value: "3", label: "Three" },
  ]}
/>

使用上面这种方式,你仍然可以限制children的类型,但是不会打破组件的可组合性 😉

相关推荐
沙漠之主33 分钟前
C++编程教学设计资料:从入门到实战的完整课程方案
java·前端·c++
hasty38 分钟前
不上传新包,也能改变用户拿到的版本:npm dist-tag 的 OIDC 权限治理
前端·npm·node.js
Csvn1 小时前
diff 算法(虚拟 DOM Reconciliation)
前端
前端snow2 小时前
ai agent --- 文件存储
前端
Frag0ut2 小时前
Chrome四大版本获取及共存指南:Stable/Beta/Dev/Canary
前端·chrome·浏览器·dev·beta·canary·共存版
IT_陈寒4 小时前
SpringBoot自动配置坑了我一把,原来是这样绕过去的
前端·人工智能·后端
广州华水科技4 小时前
单北斗GNSS变形监测在大坝安全监测中的应用与优势
前端
zeng不错4 小时前
B站 173 个投稿活动看到眼瞎?我写了个扩展,主打一个精准打击
前端
Latchh4 小时前
前端导出的JPEG红字发糊,质量要拉到100才清楚
前端·图像处理·人工智能·计算机视觉
默_笙5 小时前
🚦 请三个 AI 考官给 RAG 打分:量化评估实战(下)
前端·javascript