@typespec/http-server-js
Version:
TypeSpec HTTP server code generator for JavaScript
70 lines (57 loc) • 2.36 kB
text/typescript
// Copyright (c) Microsoft Corporation
// Licensed under the MIT license.
import { Union, UnionVariant } from "@typespec/compiler";
import { JsContext, Module, PartialUnionSynthetic } from "../ctx.js";
import { parseCase } from "../util/case.js";
import { emitDocumentation } from "./documentation.js";
import { emitTypeReference } from "./reference.js";
/**
* Emit an inline union type. This will automatically import any referenced types that are part of the union.
*
* @param ctx - The emitter context.
* @param variants - The variants of the union.
* @param module - The module that this union is written into.
* @returns a string that can be used as a type reference
*/
export function emitUnionType(ctx: JsContext, variants: UnionVariant[], module: Module): string {
// Treat empty unions as never so that we always return a good type reference here.
if (variants.length === 0) return "never";
const variantTypes: string[] = [];
for (const [_, v] of variants.entries()) {
const name = emitTypeReference(ctx, v.type, v, module);
variantTypes.push(name);
}
return variantTypes.join(" | ");
}
/**
* Emits a union type declaration as an alias.
*
* This is rare in TypeScript, but may occur in some niche cases where an alias is desirable.
*
* @param ctx - The emitter context.
* @param union - The union to emit.
* @param module - The module that this union declaration is written into.
* @param altName - An alternative name to use for the union if it is not named.
*/
export function* emitUnion(
ctx: JsContext,
union: Union | PartialUnionSynthetic,
module: Module,
altName?: string,
): Iterable<string> {
const name = union.name ? parseCase(union.name).pascalCase : altName;
const isPartialSynthetic = union.kind === "partialUnion";
if (name === undefined) {
throw new Error("Internal Error: Union name is undefined");
}
if (!isPartialSynthetic) yield* emitDocumentation(ctx, union);
const variants = isPartialSynthetic
? union.variants.map((v) => [v.name, v] as const)
: union.variants.entries();
const variantTypes = [...variants].map(([_, v]) =>
emitTypeReference(ctx, v.type, v, module, {
altName: name + parseCase(String(v.name)).pascalCase,
}),
);
yield `export type ${name} = ${variantTypes.length === 0 ? "never" : variantTypes.join(" | ")};`;
}