【发布时间】:2019-08-14 23:44:35
【问题描述】:
我想使用功能组合管道来构建对象,同时保持类型安全。我应该使用哪些类型的可组合函数将它们拼接在一起?
我有一个带有一些输入数据的对象,我的目标是使用可组合函数对输入数据执行计算。
例如,在下面的代码中,我从一个 sideLength 值开始;然后用三个独立的函数添加计算值(面积、周长和立方体面积);每个人都对自己的知识负责。像 cubeArea 这样的一些计算是基于管道中先前的计算。
import * as R from "ramda";
interface ISquare {
sideLength: number;
area: number;
circumference: number;
cubeArea: number;
}
type ISquareBase = Pick<ISquare, "sideLength">;
type ISquareWithArea = Pick<ISquare, "area" | "sideLength">;
type ISquareWithCircumference = Pick<ISquare, "circumference" | "sideLength">;
type ISquareWithCubeArea = Pick<ISquare, "cubeArea" | "sideLength">;
const addArea = (shape: ISquareBase): ISquareWithArea => ({
...shape,
area: shape.sideLength * shape.sideLength
});
const addCircumference = (shape: ISquareBase): ISquareWithCircumference => ({
...shape,
circumference: shape.sideLength * 4
});
const addCubeArea = (shape: ISquareWithArea): ISquareWithCubeArea => ({
...shape,
cubeArea: shape.area * shape.sideLength
});
const buildSquare = R.compose(
addArea, // { sideLength: 2, area: 4 }
addCircumference, // { sideLength: 2, area: 4, circumference: 8 }
addCubeArea // { sideLength: 2, area: 4, circumference: 8, cubeArea: 8 }
);
const initialSquare: ISquareBase = { sideLength: 2 };
// The below line gives typescript error:
// Argument of type 'Pick<ISquare, "sideLength">' is not assignable to parameter of type 'Pick<ISquare, "sideLength" | "area">'.
// Property 'area' is missing in type 'Pick<ISquare, "sideLength">' but required in type 'Pick<ISquare, "sideLength" | "area">'.
const calculatedSquare: ISquare = buildSquare(initialSquare);
console.log(calculatedSquare);
// Expect: { sideLength: 2, circumference: 8, area: 4, cubeArea: 8 }
当我尝试使用上面的组合函数 buildSquare 时,Typescript 出现类型错误。
Argument of type 'Pick<ISquare, "sideLength">' is not assignable to parameter of type 'Pick<ISquare, "sideLength" | "area">'.
Property 'area' is missing in type 'Pick<ISquare, "sideLength">' but required in type 'Pick<ISquare, "sideLength" | "area">'.
我可以放宽类型签名以使其正常工作,但是在运行 addArea 中的面积计算之前,我无法确保 addCubeArea 无法运行的类型。
如何在保持类型安全的同时做到这一点?有没有我可以使用的替代类型结构?
【问题讨论】:
-
顺便说一句,我会使用咖喱构造函数而不是组合。即使传递属性的顺序不同,您也可以创建自定义包装器(例如
f => c => a => d => b => f(a) (b) (c) (d)以相应地修改构造函数..
标签: typescript functional-programming