• 日本語
  • Result を変換する

    mapmapError 関数を使うと、Result の型(Success または Failure)を変えずに、内部の値を変換できます。

    map - 成功値を変換する

    map 関数は Result の成功値を変換します。 ResultFailure の場合は、変更されずにそのまま通過します。

    基本的な使い方

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const result: Result.Result<number, never>
    result
    =
    import Result
    Result
    .
    const pipe: <Result.Result<2, never>, Result.Result<number, never>>(a: Result.Result<2, never>, ab: (a: Result.Result<2, never>) => Result.Result<number, never>) => Result.Result<number, never> (+25 overloads)
    pipe
    (
    import Result
    Result
    .
    const succeed: <2>(value: 2) => Result.Result<2, never> (+1 overload)
    succeed
    (2),
    import Result
    Result
    .
    const map: <Result.Result<2, never>, number>(fn: (a: 2) => number) => (result: Result.Result<2, never>) => Result.Result<number, never> (+1 overload)
    map
    ((
    value: 2
    value
    ) =>
    value: 2
    value
    * 10),
    ); // { type: 'Success', value: 20 }

    ResultFailure の場合

    入力が Failure の場合、map は何もせず、Failure をそのまま返します。

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const result: Result.Result<number, "error">
    result
    =
    import Result
    Result
    .
    const pipe: <Result.Result<never, "error">, Result.Result<number, "error">>(a: Result.Result<never, "error">, ab: (a: Result.Result<never, "error">) => Result.Result<number, "error">) => Result.Result<number, "error"> (+25 overloads)
    pipe
    (
    import Result
    Result
    .
    const fail: <"error">(error: "error") => Result.Result<never, "error"> (+1 overload)
    fail
    ('error'),
    import Result
    Result
    .
    const map: <Result.Result<never, "error">, number>(fn: (a: never) => number) => (result: Result.Result<never, "error">) => Result.Result<number, "error"> (+1 overload)
    map
    ((
    value: never
    value
    ) =>
    value: never
    value
    * 10),
    ); // { type: 'Failure', error: 'error' }

    例:表示用のデータフォーマット

    よくある使い方として、生データを表示に適した形式に変換する例があります。

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    type
    type ProductRow = {
        id: number;
        name: string;
        priceInCents: number;
    }
    ProductRow
    = {
    id: number
    id
    : number;
    name: string
    name
    : string;
    priceInCents: number
    priceInCents
    : number;
    }; type
    type ProductView = {
        id: string;
        name: string;
        price: string;
    }
    ProductView
    = {
    id: string
    id
    : string;
    name: string
    name
    : string;
    price: string
    price
    : string;
    }; const
    const formatPrice: (cents: number) => string
    formatPrice
    = (
    cents: number
    cents
    : number): string => `$${(
    cents: number
    cents
    / 100).
    Number.toFixed(fractionDigits?: number): string

    Returns a string representing a number in fixed-point notation.

    @paramfractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
    toFixed
    (2)}`;
    const
    const toProductView: (product: ProductRow) => ProductView
    toProductView
    = (
    product: ProductRow
    product
    :
    type ProductRow = {
        id: number;
        name: string;
        priceInCents: number;
    }
    ProductRow
    ):
    type ProductView = {
        id: string;
        name: string;
        price: string;
    }
    ProductView
    => ({
    id: string
    id
    :
    var String: StringConstructor
    (value?: any) => string

    Allows manipulation and formatting of text strings and determination and location of substrings within strings.

    String
    (
    product: ProductRow
    product
    .
    id: number
    id
    ),
    name: string
    name
    :
    product: ProductRow
    product
    .
    name: string
    name
    ,
    price: string
    price
    :
    const formatPrice: (cents: number) => string
    formatPrice
    (
    product: ProductRow
    product
    .
    priceInCents: number
    priceInCents
    ),
    }); const
    const getProductForDisplay: (id: number) => Result.ResultAsync<ProductView, "NotFound">
    getProductForDisplay
    = (
    id: number
    id
    : number):
    import Result
    Result
    .
    type ResultAsync<T, E> = Promise<Result.Result<T, E>>

    An asynchronous variant of Result , wrapped in a Promise.

    @typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@example
    import { Result } from '@praha/byethrow';
    
    const fetchData = async (): Result.ResultAsync<string, Error> => {
      try {
        const data = await fetch('...');
        return { type: 'Success', value: await data.text() };
      } catch (err) {
        return { type: 'Failure', error: err as Error };
      }
    };
    @categoryCore Types
    ResultAsync
    <
    type ProductView = {
        id: string;
        name: string;
        price: string;
    }
    ProductView
    , 'NotFound'> => {
    return
    import Result
    Result
    .
    const pipe: <Result.ResultAsync<ProductRow, "NotFound">, Result.ResultAsync<ProductView, "NotFound">>(a: Result.ResultAsync<ProductRow, "NotFound">, ab: (a: Result.ResultAsync<ProductRow, "NotFound">) => Result.ResultAsync<ProductView, "NotFound">) => Result.ResultAsync<ProductView, "NotFound"> (+25 overloads)
    pipe
    (
    const fetchProduct: (id: number) => Result.ResultAsync<ProductRow, "NotFound">
    fetchProduct
    (
    id: number
    id
    ),
    import Result
    Result
    .
    const map: <Result.ResultAsync<ProductRow, "NotFound">, ProductView>(fn: (a: ProductRow) => ProductView) => (result: Result.ResultAsync<ProductRow, "NotFound">) => Result.ResultAsync<ProductView, "NotFound"> (+1 overload)
    map
    (
    const toProductView: (product: ProductRow) => ProductView
    toProductView
    ),
    ); }; // 生の商品データを UI に適した形式に変換

    mapError - 失敗値を変換する

    mapError 関数は Result の失敗値を変換します。 ResultSuccess の場合は、変更されずにそのまま通過します。

    基本的な使い方

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const result: Result.Result<never, Error>
    result
    =
    import Result
    Result
    .
    const pipe: <Result.Result<never, "NotFound">, Result.Result<never, Error>>(a: Result.Result<never, "NotFound">, ab: (a: Result.Result<never, "NotFound">) => Result.Result<never, Error>) => Result.Result<never, Error> (+25 overloads)
    pipe
    (
    import Result
    Result
    .
    const fail: <"NotFound">(error: "NotFound") => Result.Result<never, "NotFound"> (+1 overload)
    fail
    ('NotFound'),
    import Result
    Result
    .
    const mapError: <Result.Result<never, "NotFound">, Error>(fn: (a: "NotFound") => Error) => (result: Result.Result<never, "NotFound">) => Result.Result<never, Error> (+1 overload)
    mapError
    ((
    error: "NotFound"
    error
    ) => new
    var Error: ErrorConstructor
    new (message?: string, options?: ErrorOptions) => Error (+1 overload)
    Error
    (
    error: "NotFound"
    error
    )),
    ); // { type: 'Failure', error: Error('NotFound') }

    Result が Success の場合

    入力が Success の場合、mapError は何もせず、Success をそのまま返します。

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const result: Result.Result<123, Error>
    result
    =
    import Result
    Result
    .
    const pipe: <Result.Result<123, never>, Result.Result<123, Error>>(a: Result.Result<123, never>, ab: (a: Result.Result<123, never>) => Result.Result<123, Error>) => Result.Result<123, Error> (+25 overloads)
    pipe
    (
    import Result
    Result
    .
    const succeed: <123>(value: 123) => Result.Result<123, never> (+1 overload)
    succeed
    (123),
    import Result
    Result
    .
    const mapError: <Result.Result<123, never>, Error>(fn: (a: never) => Error) => (result: Result.Result<123, never>) => Result.Result<123, Error> (+1 overload)
    mapError
    ((
    error: never
    error
    ) => new
    var Error: ErrorConstructor
    new (message?: string, options?: ErrorOptions) => Error (+1 overload)
    Error
    (
    error: never
    error
    )),
    ); // { type: 'Success', value: 123 }

    例:内部エラーを HTTP レスポンスに変換

    よくある使い方として、ドメイン固有のエラーを標準化された HTTP エラーレスポンスに変換する例があります。

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    type
    type DomainError = {
        type: "NotFound";
        resource: string;
    } | {
        type: "ValidationError";
        field: string;
        message: string;
    } | {
        type: "Unauthorized";
    }
    DomainError
    =
    | {
    type: "NotFound"
    type
    : 'NotFound';
    resource: string
    resource
    : string }
    | {
    type: "ValidationError"
    type
    : 'ValidationError';
    field: string
    field
    : string;
    message: string
    message
    : string }
    | {
    type: "Unauthorized"
    type
    : 'Unauthorized' };
    type
    type HttpError = {
        status: number;
        body: {
            error: string;
            details?: string;
        };
    }
    HttpError
    = {
    status: number
    status
    : number;
    body: {
        error: string;
        details?: string;
    }
    body
    : {
    error: string
    error
    : string;
    details?: string | undefined
    details
    ?: string };
    }; const
    const toHttpError: (error: DomainError) => HttpError
    toHttpError
    = (
    error: DomainError
    error
    :
    type DomainError = {
        type: "NotFound";
        resource: string;
    } | {
        type: "ValidationError";
        field: string;
        message: string;
    } | {
        type: "Unauthorized";
    }
    DomainError
    ):
    type HttpError = {
        status: number;
        body: {
            error: string;
            details?: string;
        };
    }
    HttpError
    => {
    switch (
    error: DomainError
    error
    .
    type: "NotFound" | "ValidationError" | "Unauthorized"
    type
    ) {
    case 'NotFound': return {
    status: number
    status
    : 404,
    body: {
        error: string;
        details?: string;
    }
    body
    : {
    error: string
    error
    : 'Not Found',
    details?: string | undefined
    details
    : `${
    error: {
        type: "NotFound";
        resource: string;
    }
    error
    .
    resource: string
    resource
    } was not found` },
    }; case 'ValidationError': return {
    status: number
    status
    : 400,
    body: {
        error: string;
        details?: string;
    }
    body
    : {
    error: string
    error
    : 'Bad Request',
    details?: string | undefined
    details
    : `${
    error: {
        type: "ValidationError";
        field: string;
        message: string;
    }
    error
    .
    field: string
    field
    }: ${
    error: {
        type: "ValidationError";
        field: string;
        message: string;
    }
    error
    .
    message: string
    message
    }` },
    }; case 'Unauthorized': return {
    status: number
    status
    : 401,
    body: {
        error: string;
        details?: string;
    }
    body
    : {
    error: string
    error
    : 'Unauthorized' },
    }; } }; const
    const handleRequest: () => Result.ResultAsync<{
        data: string;
    }, HttpError>
    handleRequest
    = ():
    import Result
    Result
    .
    type ResultAsync<T, E> = Promise<Result.Result<T, E>>

    An asynchronous variant of Result , wrapped in a Promise.

    @typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@example
    import { Result } from '@praha/byethrow';
    
    const fetchData = async (): Result.ResultAsync<string, Error> => {
      try {
        const data = await fetch('...');
        return { type: 'Success', value: await data.text() };
      } catch (err) {
        return { type: 'Failure', error: err as Error };
      }
    };
    @categoryCore Types
    ResultAsync
    <{
    data: string
    data
    : string },
    type HttpError = {
        status: number;
        body: {
            error: string;
            details?: string;
        };
    }
    HttpError
    > => {
    return
    import Result
    Result
    .
    const pipe: <Result.ResultAsync<{
        data: string;
    }, DomainError>, Result.ResultAsync<{
        data: string;
    }, HttpError>>(a: Result.ResultAsync<{
        data: string;
    }, DomainError>, ab: (a: Result.ResultAsync<{
        data: string;
    }, DomainError>) => Result.ResultAsync<{
        data: string;
    }, HttpError>) => Result.ResultAsync<{
        data: string;
    }, HttpError> (+25 overloads)
    pipe
    (
    const processRequest: () => Result.ResultAsync<{
        data: string;
    }, DomainError>
    processRequest
    (),
    import Result
    Result
    .
    const mapError: <Result.ResultAsync<{
        data: string;
    }, DomainError>, HttpError>(fn: (a: DomainError) => HttpError) => (result: Result.ResultAsync<{
        data: string;
    }, DomainError>) => Result.ResultAsync<{
        data: string;
    }, HttpError> (+1 overload)
    mapError
    (
    const toHttpError: (error: DomainError) => HttpError
    toHttpError
    ),
    ); }; // ドメインエラーを HTTP 適切なエラーレスポンスに変換

    mapmapError の組み合わせ

    同じパイプラインで mapmapError の両方を使って、成功値と失敗値の両方を変換できます。

    データベースからユーザーを取得する関数があるとします。 生データは UI 用にフォーマットが必要で、内部エラーコードはユーザーフレンドリーなメッセージに変換する必要がある場合を考えます。

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const toView: (row: UserRow) => UserView
    toView
    = (
    row: UserRow
    row
    :
    type UserRow = {
        id: number;
        first_name: string;
        last_name: string;
        created_at: string;
    }
    UserRow
    ):
    type UserView = {
        id: string;
        fullName: string;
        memberSince: string;
    }
    UserView
    => ({
    id: string
    id
    :
    var String: StringConstructor
    (value?: any) => string

    Allows manipulation and formatting of text strings and determination and location of substrings within strings.

    String
    (
    row: UserRow
    row
    .
    id: number
    id
    ),
    fullName: string
    fullName
    : `${
    row: UserRow
    row
    .
    first_name: string
    first_name
    } ${
    row: UserRow
    row
    .
    last_name: string
    last_name
    }`,
    memberSince: string
    memberSince
    : new
    var Date: DateConstructor
    new (value: number | string | Date) => Date (+4 overloads)
    Date
    (
    row: UserRow
    row
    .
    created_at: string
    created_at
    ).
    Date.toLocaleDateString(locales?: Intl.LocalesArgument, options?: Intl.DateTimeFormatOptions): string (+2 overloads)

    Converts a date to a string by using the current or specified locale.

    @paramlocales A locale string, array of locale strings, Intl.Locale object, or array of Intl.Locale objects that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.@paramoptions An object that contains one or more properties that specify comparison options.
    toLocaleDateString
    (),
    }); const
    const toHttpError: (error: DatabaseError) => HttpError
    toHttpError
    = (
    error: DatabaseError
    error
    :
    type DatabaseError = "RECORD_NOT_FOUND" | "CONNECTION_FAILED" | "TIMEOUT"
    DatabaseError
    ):
    type HttpError = {
        status: number;
        body: {
            error: string;
            details?: string;
        };
    }
    HttpError
    => {
    switch (
    error: DatabaseError
    error
    ) {
    case 'RECORD_NOT_FOUND': return {
    status: number
    status
    : 404,
    body: {
        error: string;
        details?: string;
    }
    body
    : {
    error: string
    error
    : 'User Not Found',
    details?: string | undefined
    details
    : 'The requested user does not exist.',
    }, }; case 'CONNECTION_FAILED': case 'TIMEOUT': return {
    status: number
    status
    : 503,
    body: {
        error: string;
        details?: string;
    }
    body
    : {
    error: string
    error
    : 'Service Unavailable',
    details?: string | undefined
    details
    : 'Please try again later.',
    }, }; } }; const
    const getUserForView: (id: number) => Result.ResultAsync<UserView, HttpError>
    getUserForView
    = (
    id: number
    id
    : number):
    import Result
    Result
    .
    type ResultAsync<T, E> = Promise<Result.Result<T, E>>

    An asynchronous variant of Result , wrapped in a Promise.

    @typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@example
    import { Result } from '@praha/byethrow';
    
    const fetchData = async (): Result.ResultAsync<string, Error> => {
      try {
        const data = await fetch('...');
        return { type: 'Success', value: await data.text() };
      } catch (err) {
        return { type: 'Failure', error: err as Error };
      }
    };
    @categoryCore Types
    ResultAsync
    <
    type UserView = {
        id: string;
        fullName: string;
        memberSince: string;
    }
    UserView
    ,
    type HttpError = {
        status: number;
        body: {
            error: string;
            details?: string;
        };
    }
    HttpError
    > => {
    return
    import Result
    Result
    .
    const pipe: <Result.ResultAsync<UserRow, DatabaseError>, Result.ResultAsync<UserView, DatabaseError>, Result.ResultAsync<UserView, HttpError>>(a: Result.ResultAsync<UserRow, DatabaseError>, ab: (a: Result.ResultAsync<UserRow, DatabaseError>) => Result.ResultAsync<UserView, DatabaseError>, bc: (b: Result.ResultAsync<UserView, DatabaseError>) => Result.ResultAsync<...>) => Result.ResultAsync<...> (+25 overloads)
    pipe
    (
    const fetchUser: (id: number) => Result.ResultAsync<UserRow, DatabaseError>
    fetchUser
    (
    id: number
    id
    ),
    import Result
    Result
    .
    const map: <Result.ResultAsync<UserRow, DatabaseError>, UserView>(fn: (a: UserRow) => UserView) => (result: Result.ResultAsync<UserRow, DatabaseError>) => Result.ResultAsync<UserView, DatabaseError> (+1 overload)
    map
    (
    const toView: (row: UserRow) => UserView
    toView
    ),
    import Result
    Result
    .
    const mapError: <Result.ResultAsync<UserView, DatabaseError>, HttpError>(fn: (a: DatabaseError) => HttpError) => (result: Result.ResultAsync<UserView, DatabaseError>) => Result.ResultAsync<UserView, HttpError> (+1 overload)
    mapError
    (
    const toHttpError: (error: DatabaseError) => HttpError
    toHttpError
    ),
    ); }

    リファレンス

    関数目的
    map(fn)Result の成功値を変換する
    mapError(fn)Result のエラー値を変換する