Ответ на ваш вопрос зависит от конкретной реализации Maybe, поэтому я включаю один из них, который я использую ниже. По сути, сейчас вам нужно явно аннотировать функцию как тип защиты, чтобы это работало. Поговаривали о поддержке not T
типов, которые необходимы для работы !isNone()
, но пока этого не произошло. Код ниже работает, хотя:
const MaybeTag = Symbol("Maybe");
type Nothing<T> = { [MaybeTag]?: T; name: "Nothing" } ;
type Just<T> ={ [MaybeTag]?: T; name: "Just"; value: T } ;
type Maybe<T> = Just<T> | Nothing<T>
const Maybe = {
Just<T>(value: T): Just<T> {
return { name: "Just", value };
},
Nothing<T = never>(): Nothing<T> {
return { name: "Nothing" };
},
isNothing<T>(maybe: Maybe<T>): maybe is Nothing<T> {
return maybe.name === "Nothing";
},
isJust<T>(maybe: Maybe<T>): maybe is Just<T> {
return maybe.name === "Just";
},
fromNull<T>(value: T | null | undefined): Maybe<T> {
if (value == null) return Maybe.Nothing();
return Maybe.Just(value);
}
}
const x: number[] = [1, 2, 3, null]
.map(Maybe.fromNull)
.filter(Maybe.isJust)
.map(x => x.value) // x is Just<number> as expected
const x: number[] = [1, 2, 3, null]
.map(Maybe.fromNull)
// Note the explicit type guard
.filter(function<T>(x: Maybe<T>): x is Just<T> {
return !Maybe.isNothing(x);
})
.map(x => x.value) // x is Just<number> as expected