已发布 上游基线 bf46254 原文 ↗ 在 GitHub 编辑

Equivalence

为 TypeScript 值定义并自定义等价关系。

Equivalence 模块提供了一种在 TypeScript 中定义值之间等价关系的方式。等价关系是一种自反、对称且传递的二元关系,它为“两个值何时应被视为等价”建立了形式化的定义。

什么是 Equivalence?

一个 Equivalence<A> 表示一个函数,它比较两个类型为 A 的值并判断它们是否等价。与使用 === 的简单相等性检查相比,这种方式更灵活、也更可定制。

Equivalence 的结构如下:

interface Equivalence<A> {
  (self: A, that: A): boolean
}

使用内置的 Equivalence

该模块为常见数据类型提供了若干内置的等价关系:

Equivalence说明
string对字符串使用严格相等(===
number对数字使用严格相等(===
boolean对布尔值使用严格相等(===
symbol对 symbol 使用严格相等(===
bigint对 bigint 使用严格相等(===
Date按时间戳比较 Date 对象

示例(使用内置的 Equivalence)

import { Equivalence } from "effect"

console.log(Equivalence.string("apple", "apple"))
// Output: true

console.log(Equivalence.string("apple", "orange"))
// Output: false

console.log(Equivalence.Date(new Date(2023, 1, 1), new Date(2023, 1, 1)))
// Output: true

console.log(Equivalence.Date(new Date(2023, 1, 1), new Date(2023, 10, 1)))
// Output: false

派生 Equivalence

对于更复杂的数据结构,你可能需要自定义的等价关系。Equivalence 模块允许你通过 Equivalence.mapInput 函数,从已有的 Equivalence 实例派生出新的实例。

示例(为对象创建自定义的 Equivalence)

import { Equivalence } from "effect"

interface User {
  readonly id: number
  readonly name: string
}

// Create an equivalence that compares User objects based only on the id
const equivalence = Equivalence.mapInput(
  Equivalence.number, // Base equivalence for comparing numbers
  (user: User) => user.id, // Function to extract the id from a User
)

// Compare two User objects: they are equivalent if their ids are the same
console.log(equivalence({ id: 1, name: "Alice" }, { id: 1, name: "Al" }))
// Output: true

Equivalence.mapInput 函数接收两个参数:

  1. 你想用作基础的现有 Equivalence(这里是 Equivalence.number,用于比较数字)。
  2. 一个从你的数据结构中提取值的函数,该值用于等价性检查(这里是 (user: User) => user.id)。