正确键入Box类

时间:2018-04-27 14:15:31

标签: typescript

我在使用PureScript进行函数式编程blog post之后。在JavaScript中有一个Box的示例:

const Box = x => ({
    map: f => Box(f(x)),
    fold: f => f(x),
    inspect: () => `Box(${x})`
});

我想使用TypeScript对其进行输入,以便像这样对代码进行语法检查:

const nextCharForNumberString = str => 
  Box(str)
  .map(s => s.trim()) 
  .map(s => new Number(s)) 
  .map(i => i + 1) 
  .map(i => String.fromCharCode(i)) 
  .fold(c => c.toLowerCase());

我试图像这样输入Box:

interface IBox<T> {
    map: <U>(T) => IBox<U>;
    fold: <U>(T) => U;
    inspect: (T) => string;
}

const Box: <T>(x: T) => IBox<T> = x => ({
    map: f => Box(f(x)),
    fold: f => f(x),
    inspect: () => `Box(${x})`
});

让我知道如何正确输入Box功能。为了简化语法,我也试过了:

function Box<T>(x: T): IBox<T> {
    return {
        map: <U>(f): IBox<U> => Box(f(x)),
        fold: <U>(f): U => f(x),
        inspect: () => `Box(${x})`
    };
}

我的尝试都没有。我希望在编译时捕获它:

const s: IBox<String> = Box(5)
    .map(x => x * x)
    .map(x => x.toString())
    .map(x => x * x)
    .fold(x => x);

在我看来,使用TypeScript可以实现这一点。任何见解将不胜感激!

1 个答案:

答案 0 :(得分:2)

当然,我认为你非常接近。这是一种键入Box<T>界面的方法:

interface Box<T> {
  map<U>(f: (t: T) => U): Box<U>;
  fold<U>(f: (t: T) => U): U;
  inspect(): string;
}

这是一种键入Box函数的方法,它接受T类型的参数并生成Box<T>(您可以使用Box作为类型名称和函数名称,因为值名称和类型名称存在于不同的名称空间中):

const Box = <T>(x: T): Box<T> => ({
  map: f => Box(f(x)),
  fold: f => f(x),
  inspect: () => `Box(${x})`
}); // compiles fine

然后您将在编译时捕获问题,如下所示:

const badS = Box(5)
  .map(x => x * x)
  .map(x => x.toString())
  .map(x => x * x) // error, x is a string, you cant multiply it
  .fold(x => x);

能够修复它:

const goodS = Box(5)
.map(x => x * x)
.map(x => x.toString())
.fold(x => x); // goodS is type string

console.log(goodS); "25"

希望有所帮助;祝你好运!