访问嵌套属性的通用类型

时间:2019-08-30 23:41:18

标签: typescript generics monads

我正在尝试在TypeScript中实现monad;尤其是this example中的join方法。

要解决的问题如下:

const mm3 = new Maybe(new Maybe(3)); // Maybe<Maybe<number>>
const m3 = mm3.join();               // Maybe<number>

join方法取消嵌套两个Maybe的嵌套。但是,在调用Maybe时可以进入join的三种状态。预期的输出如下所示。

new Maybe(new Maybe(3)).join(); // Maybe<number>(3)
new Maybe<number>(null).join(); // Maybe<number>(null)
new Maybe(3).join();            // 3 - Not the normal use-case for join()

模糊地尝试实施...

interface IMonad<T> {
    join(): T; // Works for cases #1 and #3 above but
               // really I want to express that we're
               // returning an IMonad<number> in the examples.
               // Or even better, a Maybe<number> in the case of Maybe 
}

class Maybe<T> implements IMonad<T> {

    private value: T | null;

    public constructor(value: T | null | undefined) {
        this.value = (value === null || value === undefined) ? null : value;
    }

    public join(): T {
        if (this.value === null) {
            return Maybe.of<??>(null); // 'number' in these examples
        } else {
            return this.value;
        }
    }

}

我正在努力弄清这可能如何工作。有任何想法吗? TypeScript甚至可以使用,还是我需要higher kinded types

1 个答案:

答案 0 :(得分:2)

只要您不想代表Monad本身,就很容易实现Maybe的单个 instances (例如Monad),需要higher-kinded types ...,而TypeScript对此没有直接支持。 (似乎some peoplecome up with一些间接支持,但是没有足够干净的地方,我想在这里推荐)

如果您要强烈键入Maybe.prototype.join(),而不必担心代码中的“ Monad”,我建议使用通用的this parameter,如下所示:

class Maybe<T> {
  constructor(public value?: T) {}
  join<U>(this: Maybe<Maybe<U>>) { // this parameter
    return new Maybe(
      typeof this.value === "undefined" ? undefined : this.value.value
    );
  }
}

(我在这里仅将undefined作为“无”值;如果需要,您可以添加对null的支持)

this参数要求在匹配类型的对象上将其作为方法调用。因此,通过将join()的{​​{1}}设为某个通用this的{​​{1}},我们可以保证Maybe<Maybe<U>>本身(如果不是U的话this.value属性。

让我们测试一下:

undefined

这正是您想要看到的。另请注意,调用value是编译时错误:

const mm3 = new Maybe(new Maybe(3)); // Maybe<Maybe<number>>
const m3 = mm3.join(); // Maybe<number>

这对我来说似乎是正确的行为;您不能m3.join()使用非嵌套的monad。

好的,希望能有所帮助;祝好运!

Link to code