Open4

typescript

takutaku

既存のTypeを使って、値だけundefinedを許す値を返す

type Uninitialized<T extends object> = {
[key in keyof T]?: T[key];
};

takutaku

typescriptでResult型を書く

export type Result<T, F> = Success<T, F> | Failure<T, F>;

interface IResult<T, F> {
    isSuccess(): this is Success<T, F>;
    isFailure(): this is Failure<T, F>;
    readonly value: T | F;
    map<R, L>(fnL: (f: F) => L, fnR: (t: T) => R): Result<R, L>;
    mapR<R>(r: (t: T) => R): Result<R, F>;
    mapL<L>(l: (f: F) => L): Result<T, L>;

    fmap<R, L>(fnL: (f: F) => Result<R, L>, fnR: (t: T) => Result<R, L>): Result<R, L>;
    fmapR<R>(fnR: (t: T) => Result<R, F>): Result<R, F>;
    fmapL<L>(fnL: (t: F) => Result<T, L>): Result<T, L>;
}

export class Success<T, F> implements IResult<T, F> {
    constructor(value: T) {
        this.value = value;
    }

    readonly value: T;

    isSuccess() {
        return true;
    }

    isFailure() {
        return false;
    }

    fmap<R, L>(fnL: (f: F) => Result<R, L>, fnR: (t: T) => Result<R, L>): Result<R, L> {
        return fnR(this.value);
    }

    fmapR<R>(fnR: (t: T) => Result<R, F>): Result<R, F> {
        return fnR(this.value);
    }

    fmapL<L>(fnL: (t: F) => Result<T, L>): Result<T, L> {
        return success<T, L>(this.value);
    }

    map<R, L>(fnL: (f: F) => L, fnR: (t: T) => R): Result<R, L> {
        return success<R, L>(fnR(this.value));
    }

    mapR<R>(fnR: (t: T) => R): Result<R, F> {
        return success<R, F>(fnR(this.value));
    }

    mapL<L>(_: (f: F) => L): Result<T, L> {
        return success<T, L>(this.value);
    }
}

export class Failure<T, F> implements IResult<T, F> {
    constructor(value: F) {
        this.value = value;
    }

    readonly value: F;

    isSuccess() {
        return false;
    }

    isFailure() {
        return true;
    }

    fmap<R, L>(fnL: (f: F) => Result<R, L>, fnR: (t: T) => Result<R, L>): Result<R, L> {
        return fnL(this.value);
    }

    fmapR<R>(fnR: (t: T) => Result<R, F>): Result<R, F> {
        return failure(this.value);
    }

    fmapL<L>(fnL: (t: F) => Result<T, L>): Result<T, L> {
        return fnL(this.value);
    }

    map<R, L>(fnL: (f: F) => L, fnR: (t: T) => R): Result<R, L> {
        return failure<R, L>(fnL(this.value));
    }

    mapR<R>(_: (t: T) => R): Result<R, F> {
        return failure<R, F>(this.value);
    }

    mapL<L>(fnL: (f: F) => L): Result<T, L> {
        return failure<T, L>(fnL(this.value));
    }
}

export function success<T, F>(value: T) {
    return new Success<T, F>(value);
}

export function failure<T, F>(value: F) {
    return new Failure<T, F>(value);
}

takutaku

ただしPromise<Result>になると途端に扱いづらくなるのは難点。。

takutaku

こんな書き方出来るの知らんかった。
const {attributes: { email, preferred_username, "custom:department": department },
} = await AuthApi.userProifle();