mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-04-09 02:09:12 +00:00
refactor(question): effectify QuestionService (#17432)
This commit is contained in:
@@ -15,3 +15,40 @@ export const withStatics =
|
||||
<S extends object, M extends Record<string, unknown>>(methods: (schema: S) => M) =>
|
||||
(schema: S): S & M =>
|
||||
Object.assign(schema, methods(schema))
|
||||
|
||||
declare const NewtypeBrand: unique symbol
|
||||
type NewtypeBrand<Tag extends string> = { readonly [NewtypeBrand]: Tag }
|
||||
|
||||
/**
|
||||
* Nominal wrapper for scalar types. The class itself is a valid schema —
|
||||
* pass it directly to `Schema.decode`, `Schema.decodeEffect`, etc.
|
||||
*
|
||||
* @example
|
||||
* class QuestionID extends Newtype<QuestionID>()("QuestionID", Schema.String) {
|
||||
* static make(id: string): QuestionID {
|
||||
* return this.makeUnsafe(id)
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Schema.decodeEffect(QuestionID)(input)
|
||||
*/
|
||||
export function Newtype<Self>() {
|
||||
return <const Tag extends string, S extends Schema.Top>(tag: Tag, schema: S) => {
|
||||
type Branded = NewtypeBrand<Tag>
|
||||
|
||||
abstract class Base {
|
||||
declare readonly [NewtypeBrand]: Tag
|
||||
|
||||
static makeUnsafe(value: Schema.Schema.Type<S>): Self {
|
||||
return value as unknown as Self
|
||||
}
|
||||
}
|
||||
|
||||
Object.setPrototypeOf(Base, schema)
|
||||
|
||||
return Base as unknown as
|
||||
& (abstract new (_: never) => Branded)
|
||||
& { readonly makeUnsafe: (value: Schema.Schema.Type<S>) => Self }
|
||||
& Omit<Schema.Opaque<Self, S, {}>, "makeUnsafe">
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user