MCPcopy Create free account
hub / github.com/Effect-TS/effect / toTaggedUnion

Function toTaggedUnion

packages/effect/src/Schema.ts:6272–6331  ·  view source on GitHub ↗
(tag: Tag)

Source from the content-addressed store, hash-verified

6270 * @since 4.0.0
6271 */
6272export function toTaggedUnion<const Tag extends PropertyKey>(tag: Tag) {
6273 return <const Members extends ReadonlyArray<Constraint & { readonly Type: { readonly [K in Tag]: PropertyKey } }>>(
6274 self: Union<Members>
6275 ): toTaggedUnion<Tag, Members> => {
6276 const cases: Record<PropertyKey, unknown> = {}
6277 const discriminants: Array<PropertyKey> = []
6278 const discriminantKeys = new Set<string | symbol>()
6279 const guards: Record<PropertyKey, (u: unknown) => boolean> = {}
6280 const isAnyOf = (keys: ReadonlyArray<PropertyKey>) => (value: Members[number]["Type"]) => keys.includes(value[tag])
6281
6282 walk(self)
6283
6284 return Object.assign(self, { cases, discriminants, isAnyOf, guards, match }) as any
6285
6286 function walk(schema: Constraint) {
6287 const ast = schema.ast
6288
6289 if (
6290 SchemaAST.isUnion(ast) && "members" in schema && globalThis.Array.isArray(schema.members) &&
6291 schema.members.every(isSchema)
6292 ) {
6293 return schema.members.forEach(walk)
6294 }
6295
6296 const sentinels = SchemaAST.collectSentinels(ast)
6297 if (sentinels.length > 0) {
6298 const literal = sentinels.find((s) => s.key === tag)?.literal
6299 if (Predicate.isPropertyKey(literal)) {
6300 const key = typeof literal === "number" ? globalThis.String(literal) : literal
6301 if (discriminantKeys.has(key)) {
6302 throw new globalThis.Error(`Duplicate discriminant: ${globalThis.String(literal)}`)
6303 }
6304 discriminantKeys.add(key)
6305 discriminants.push(literal)
6306 InternalRecord.assignProperty(cases, literal, schema)
6307 InternalRecord.assignProperty(guards, literal, is(toType(schema)))
6308 return
6309 }
6310 }
6311
6312 throw new globalThis.Error("No literal or unique symbol found")
6313 }
6314
6315 function match() {
6316 if (arguments.length === 1) {
6317 const cases = arguments[0]
6318 return function(value: any) {
6319 const key = value[tag]
6320 const handler = Object.hasOwn(cases, key) ? cases[key] : undefined
6321 return handler(value)
6322 }
6323 }
6324 const value = arguments[0]
6325 const cases = arguments[1]
6326 const key = value[tag]
6327 const handler = Object.hasOwn(cases, key) ? cases[key] : undefined
6328 return handler(value)
6329 }

Callers 1

TaggedUnionFunction · 0.85

Calls 2

assignMethod · 0.80
walkFunction · 0.70

Tested by

no test coverage detected