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的类型,但是不会打破组件的可组合性 😉

相关推荐
Larcher25 分钟前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐37 分钟前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭1 小时前
如何理解HTML语义化
前端·html
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
brzhang1 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu2 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花2 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋2 小时前
场景模拟:基础路由配置
前端
六月的可乐2 小时前
实战干货-Vue实现AI聊天助手全流程解析
前端·vue.js·ai编程