访问嵌套的通用类型 属性
Accessing generic type of nested property
我正在尝试在 TypeScript 中实现一个 monad;特别是 this example.
中的 join
方法
待解决问题如下:
const mm3 = new Maybe(new Maybe(3)); // Maybe<Maybe<number>>
const m3 = mm3.join(); // Maybe<number>
join
方法解除两个 Maybe
的嵌套。但是调用join
时Maybe
可以处于三种状态。预期输出如下所示。
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?
实现 Monad
的单个 实例 非常简单,例如 Maybe
,只要您不想表示 Monad
本身,它确实需要 higher-kinded types... and TypeScript has no direct support for those, as you know. (It seems that some people have come 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
作为 "nothing" 值;如果需要,您可以添加对 null
的支持)
this
参数要求在匹配类型的对象上将其作为方法调用。因此,通过让 join()
的 this
成为某些通用 U
的 Maybe<Maybe<U>>
,我们保证 this.value
将(如果不是 undefined
)本身具有一个 value
属性.
我们来测试一下:
const mm3 = new Maybe(new Maybe(3)); // Maybe<Maybe<number>>
const m3 = mm3.join(); // Maybe<number>
这正是您想要看到的。另请注意,调用 m3.join()
是一个编译时错误:
const oops = m3.join(); // error!
/* The 'this' context of type 'Maybe<number>' is not assignable to method's
'this' of type 'Maybe<Maybe<unknown>>'. Type 'number' is not assignable
to type 'Maybe<unknown>'. */
我认为这是正确的行为;你不能 join()
一个非嵌套的 monad。
好的,希望对您有所帮助;祝你好运!
我正在尝试在 TypeScript 中实现一个 monad;特别是 this example.
中的join
方法
待解决问题如下:
const mm3 = new Maybe(new Maybe(3)); // Maybe<Maybe<number>>
const m3 = mm3.join(); // Maybe<number>
join
方法解除两个 Maybe
的嵌套。但是调用join
时Maybe
可以处于三种状态。预期输出如下所示。
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?
实现 Monad
的单个 实例 非常简单,例如 Maybe
,只要您不想表示 Monad
本身,它确实需要 higher-kinded types... and TypeScript has no direct support for those, as you know. (It seems that some people have come 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
作为 "nothing" 值;如果需要,您可以添加对 null
的支持)
this
参数要求在匹配类型的对象上将其作为方法调用。因此,通过让 join()
的 this
成为某些通用 U
的 Maybe<Maybe<U>>
,我们保证 this.value
将(如果不是 undefined
)本身具有一个 value
属性.
我们来测试一下:
const mm3 = new Maybe(new Maybe(3)); // Maybe<Maybe<number>>
const m3 = mm3.join(); // Maybe<number>
这正是您想要看到的。另请注意,调用 m3.join()
是一个编译时错误:
const oops = m3.join(); // error!
/* The 'this' context of type 'Maybe<number>' is not assignable to method's
'this' of type 'Maybe<Maybe<unknown>>'. Type 'number' is not assignable
to type 'Maybe<unknown>'. */
我认为这是正确的行为;你不能 join()
一个非嵌套的 monad。
好的,希望对您有所帮助;祝你好运!