Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Do TS: Typescript Do notation

License

NotificationsYou must be signed in to change notification settings

sondresj/dots

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JSRCI

Friendly monadic types inspired by Rust.Fully typed Do-notation and misc functional programming utils.

Warning

This project is still a work in progress, breaking changes is likely.Semantic versioning does not necessarily apply until a 1.0 release

Note

Instances of Option, Result, Task and Iter are frozen (immutable) and arenull-prototype objects

Yet another functional programming package??

There is a lot of prior art similar to this package, such asEffect-TS.DoTS aims to be pragmatic and provide a minimal api surface to get the job done with the lowest possible barrier of entry for developers new to the functional programming paradigm.However, you should probably use Effect-TS. It's an awesome library!

How does it work?

Do notation in typescript is not natively supported, but can be achieved using generator functions.However, the typescript types for Generator and Iterator assumes the same type T is yielded from a generator,to work around this, we can yield ayielder instead, which is a generator function that yields itself.This is why the monadic types here implements [Symbol.iterator] and also why theyield* operator is required in a do-block.

Example

import { Do, Done, Fail, None, type Option, Some, Task, taskify } from "dots";export class RequestError extends Error {    constructor(        public readonly status: number,        public readonly content: {            message: string;            status: string;            body: Option<any>;        },        public readonly inner: Option<Error>,    ) {        super(content.message);    }}const _taskFetch = taskify(fetch);const taskFetch: typeof _taskFetch = (...args) =>    _taskFetch(...args).mapFailure((err) => {        // Fetch rejected with no response from the uri        return new RequestError(            500,            {                message: (err as any)?.message ?? "Unknown Error",                status: "Unknown",                body: None(),            },            Some(err as any),        );    });export const request = Do.bind(function* <T>(    method: "GET" | "POST" | "PATCH" | "PUT" | "DELETE",    uri: string,    headers: Record<PropertyKey, any> = {},    body: Record<PropertyKey, any> = {},) {    const response = yield* taskFetch(uri, {        method,        headers,        body: method !== "GET" ? JSON.stringify(body) : undefined,    });    const json = yield* Task(response.json()).mapFailure((err) => {        return new RequestError(            500,            {                message: (err as any)?.message ?? "Invalid JSON Response",                status: "Unknown",                body: None(), // could be response.text() instead            },            Some(err as any),        );    });    if (response.ok) {        return Done<T, RequestError>(json as NonNullable<T>);    }    return Fail<T, RequestError>(        new RequestError(            response.status,            {                status: response.statusText,                message: "Response indicated not OK",                body: Some(json),            },            None(),        ),    );});

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp