如何通过遵循一个简单的原则在 TypeScript 中设计更好的类型
所有可维护、长寿命且使用起来仍然愉悦的 React 代码库,即使使用多年,都有一个共同点:
它们由围绕数据构建的、结构合理的组件组成。
我最喜欢的一篇关于 React 的文章完美地解释了这一点:
在 React 中定义组件 API
但即使是官方的 React 文档也强调了为应用程序数据选择正确的结构以及围绕该数据构建组件的重要性:
由于您经常向用户显示 JSON 数据模型,您会发现,如果您的模型构建正确,那么您的 UI(以及您的组件结构)将很好地映射。React
中的思考
幸运的是,有一些简单的原则可以使应用程序数据建模变得非常容易。
本文从最重要的一点开始:
我们的模型覆盖的空间应该只包括在我们的领域中有效的案例
一个简单的例子:制造汽车
虽然以下示例对于一般的 Typescript 代码库来说可能不太现实,但它的类型是每个代码库的两个基本结构的示例。
首次尝试建模汽车配置
为了制造汽车,我们可能会想到以下类型:
type PowerSource = "gas tank" | "battery"
type Engine = "electric motor" | "petrol engine" | "diesel engine"
type Fuel = "petrol" | "diesel" | "electrons"
type Car = {
engine: Engine
fuel: Fuel
powerSource: PowerSource
}
让我们看一下 Car 类型。它有三种发动机、三种燃料和两种不同的电源。
乘以2 x 3 x 3, 我们得到所有可能的汽车配置数量为 18。乍一看,一切看起来都很棒。我们很高兴 Typescript 阻止了我们将随机字符串赋值给汽车部件,并且成功避免了拼写错误。
以下示例显示了一辆有效的汽车。
const buggyCar: Car = {
engine: "petrol engine",
fuel: "diesel",
powerSource: "gas tank",
}
但加满油箱并启动引擎却会带来一个令人不快的意外:
用柴油驱动汽油发动机必死无疑。然而,这种组合却是一个有效的类型。
我们该如何设计类型来立即避免此类故障?
为我们的汽车设计更好的类型
我们首先分析领域,然后立即发现只有三种配置可以实现汽车的功能。
type ElectricCar = {
engine: "electric motor"
fuel: "electrons"
powerSource: "battery"
}
type DieselCar = {
engine: "diesel motor"
fuel: "diesel"
powerSource: "gas tank"
}
type PetrolCar = {
engine: "petrol motor"
fuel: "petrol"
powerSource: "gas tank"
}
现在我们可以将汽车类型建模为这些接口的一个联合:
type Car = PetrolCar | ElectricCar | DieselCar
新类型仅包含三辆功能正常的汽车,因为我们通过构建1+1+1=3 的和来计算案例 数量,而不是像之前那样通过2x3x3=18 的乘积来计算。 如果使用旧类型,我们需要结合测试和文档来防止汽车配置出现问题。
何必呢?
Typescript 很有帮助。即使是最初的 Typescript 也能通过捕捉拼写错误等小错误来避免 bug。但编写代码也能让我们向其他开发者传达意图或知识。或许它可以让我们更接近 Elm、Clojure 或 Haskell 等其他语言的社区。我们可以从中受益匪浅。
下一步是什么?
以下链接是深入挖掘的良好开端:
你怎么认为?
Typescript 是否改变了你对代码的看法?当我们移除类型之后,你的 Typescript 代码看起来仍然和 JavaScript 代码不同吗?
你认为 Typescript 是否让我们更接近向其他社区学习?