typescript - TypeScript 中具有类型保护和交集类型的新类型模式
问题描述
我正在阅读这篇关于 TS 中的新型模式的文章。
作者展示了使用交集类型和假盒子类型之间的区别。后者是您主要在所有实现中发现的(例如参见 fp-ts 和 lib newtype-ts),因为缺少在“交叉类型”部分末尾描述的不变量:
更重要的是,由于 TypeScript 是结构化类型的,我们可以将 newtype 的值传递到任何需要基本类型的地方。一般来说,这可能非常好,因为我们可以在原始的所有实用程序函数中使用该类型,但如果我们想保持该值的某些不变量,也可能是非常不希望的:
type SortedArray<T> =
T[] & { readonly __tag: unique symbol };
function sort<T>(array: T[]): SortedArray<T> {
return [...array].sort() as SortedArray<T>;
}
const sorted = sort([3, 7, 1]);
// no error here, but should be:
const notSortedAnymore = sorted.concat(2);
我自己在 TS 4.4 中实现了这个例子,我可能会遗漏一些东西,因为 of 的类型notSortedAnymore
显然不是 aSortedArray
而是 a number[]
。
对我来说,这似乎不是问题,因为类型系统不会被该concat
方法的使用所误导。我有一个 SortedArray,我连接数字 2,无法推断它仍然是一个 SortedArray,所以它给了我一个数字数组。
鉴于在 TS 中,对这种模式使用交集类型可以实现更简单(甚至可能更清晰)(= 您可以避免使用该lift
函数来应用简单的函数,例如concat
),为什么 newtype 模式通常是使用假盒子类型而不是交叉类型实现?我在这里想念什么?
非常感谢
最好的
解决方案
我可能会遗漏一些东西,因为类型
notSortedAnymore
显然不是 aSortedArray
而是 anumber[]
。
这不仅仅是 TS 4.4 的事情,我也尝试过旧版本的 TypeScript,结果也没有什么不同。
我相信示例中的方法选择不当(或错误?)。相反,它应该是
type SortedArray<T> = T[] & { readonly __tag: unique symbol };
function sort<T>(array: T[]): SortedArray<T> {
return [...array].sort() as SortedArray<T>;
}
const sorted = sort([3, 7, 1]);
// no error here, but should be:
sorted.push(2);
现在sorted
仍然是 aSortedArray<number>
但它的元素没有排序。结构类型的问题在于它允许调用在原始类型上定义的所有方法,无论它们是否对新类型有效。slice
会很好,push
或者pop
不是reverse
。
而且它不仅限于方法,还可以定义函数,例如
function shuffle<T extends number[]>(arr: T): T {
arr[0] = 4; // chosen by fair dice roll :-)
return arr;
}
并像使用它一样
const sorted = sort([3, 7, 1]);
const shuffled = shuffle(sorted);
whereshuffled
将被推断为 a SortedArray<number>
。
推荐阅读
- data-structures - 是否存在仅在文本文件中逐行插入和搜索特定单词的最佳数据结构?
- python - 比较2个excel文件python
- ms-access - ConcatRelated函数和第五个参数
- database-design - 跟踪订单的交付——使用触发器还是从数据中派生?
- powershell - 如果您在 vscode 中缩进,Here-string 不起作用
- css - 反应和基础:不能使用行类
- continuous-integration - Gitlab-CI:合并后参考源分支运行部署阶段
- python - 在 SQLite 中查询 FTS5 表时 fetchone 的空结果
- angular - ng build --prod 需要永远
- kubernetes - 使用 podAntiAffinity 规则确保 pod 在不同的抢占式节点上运行