syuilo / cafy

☕️ Strongly typed and lightweight validator generator

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

feature request: $.literal

rinsuki opened this issue · comments

TypeScriptにおいて、特定のLiteral typesであることを保証する。

import $ from "cafy"
import { metyakutyaInput } from "./sugoi-library"

const a = $.literal("hoge").throw(metyakutyaInput()) // => "hoge"
const b = $.either($.literal("fuga"), $.literal("piyo")).throw(metyakutyaInput()) // => "fuga" | "piyo"
import { Context } from "cafy"

export function ConstContext<Const extends string>(value: Const) {
    return class ConstContextClass<Maybe extends Const | undefined | null> extends Context<Maybe> {
        name = "Const"

        constructor(optional = false, nullable = false) {
            // its magic
            super(optional, nullable)

            this.push(v => v === value)
        }

        static with<C extends Const>(value: C) {
            return class ConstContextClass_ extends ConstContextClass<C> {}
        }

        //#region some magic
        public makeOptional(): ConstContextClass<Const | undefined> {
            return new ConstContextClass(true, false)
        }

        public makeNullable(): ConstContextClass<Const | null> {
            return new ConstContextClass(false, true)
        }

        public makeOptionalNullable(): ConstContextClass<Const | undefined | null> {
            return new ConstContextClass(true, true)
        }
        //#endregion
    }.with(value)
}

無理矢理実装したバージョン

string限定でいいのかしら

この時はstringだけでよかったからstringしか実装してないけど、numberとかもあると便利な気がする

ほかには Symbol もありそう

Genericに対してas constのようなことができそうにないから難しいかもしれない

利用者側で $.literal('foo' as const) みたいに書いてもらうしかないかな

Genericに対してas constのようなことができそうにないから難しいかもしれない

<T extends keyof any>ってすればいけた