Hyperlinkv0.8.0-beta.28

SchemaAST

SchemaAST.TemplateLiteralclasseffect/SchemaAST.ts:1104
TemplateLiteral

AST node representing a TypeScript template literal type (e.g. `user_${string}`).

Details

parts is an array of AST nodes; each part contributes to matching strings at runtime.

export class TemplateLiteral extends Base {
  readonly _tag = "TemplateLiteral"
  readonly parts: ReadonlyArray<AST>
  /** @internal */
  readonly encodedParts: ReadonlyArray<TemplateLiteralPart>

  constructor(
    parts: ReadonlyArray<AST>,
    annotations?: Schema.Annotations.Annotations,
    checks?: Checks,
    encoding?: Encoding,
    context?: Context
  ) {
    super(annotations, checks, encoding, context)
    const encodedParts: Array<TemplateLiteralPart> = []
    for (const part of parts) {
      const encoded = toEncoded(part)
      if (isTemplateLiteralPart(encoded)) {
        encodedParts.push(encoded)
      } else {
        throw new Error(`Invalid TemplateLiteral part ${encoded._tag}`)
      }
    }
    this.parts = parts
    this.encodedParts = encodedParts
  }
  /** @internal */
  getParser(recur: (ast: AST) => SchemaParser.Parser): SchemaParser.Parser {
    const parser = recur(this.asTemplateLiteralParser())
    return (oinput: Option.Option<unknown>, options: ParseOptions) =>
      Effect.mapBothEager(parser(oinput, options), {
        onSuccess: () => oinput,
        onFailure: (issue) => new SchemaIssue.Composite(this, oinput, [issue])
      })
  }
  /** @internal */
  getExpected(): string {
    return "string"
  }
  /** @internal */
  matchPart(s: string, options: ParseOptions): string | undefined {
    return segmentTemplateLiteralParts(this.encodedParts, s, options) === undefined ? undefined : s
  }
  /** @internal */
  asTemplateLiteralParser(): Arrays {
    const tuple = new Arrays(false, this.parts.map(partFromString), [])
    return decodeTo(
      string,
      tuple,
      new SchemaTransformation.Transformation(
        SchemaGetter.transformOrFail((s: string, options) => {
          const segments = segmentTemplateLiteralParts(this.encodedParts, s, options)
          if (segments !== undefined) return Effect.succeed(segments)
          return Effect.fail(
            new SchemaIssue.InvalidValue(Option.some(s), {
              message: `Expected a string matching template literal parts, got ${format(s)}`
            })
          )
        }),
        SchemaGetter.transform((parts) => parts.join(""))
      )
    )
  }
}
Referenced by 2 symbols