feature request: $.literal
rinsuki opened this issue · comments
rinsuki commented
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"
rinsuki commented
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)
}
無理矢理実装したバージョン
syuilo commented
string限定でいいのかしら
rinsuki commented
この時はstringだけでよかったからstringしか実装してないけど、numberとかもあると便利な気がする
otofune commented
ほかには Symbol もありそう
syuilo commented
Genericに対してas const
のようなことができそうにないから難しいかもしれない
syuilo commented
利用者側で $.literal('foo' as const) みたいに書いてもらうしかないかな
syuilo commented
Genericに対してas constのようなことができそうにないから難しいかもしれない
<T extends keyof any>
ってすればいけた