Skip to content

Commit

Permalink
fix: ensure nullable shows in api reference (#2010)
Browse files Browse the repository at this point in the history
Co-authored-by: fern-bot <[email protected]>
  • Loading branch information
RohinBhargava and fern-support authored Jan 21, 2025
1 parent 2db3182 commit 530833a
Showing 1 changed file with 89 additions and 76 deletions.
165 changes: 89 additions & 76 deletions packages/fern-docs/ui/src/type-shorthand/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ export function renderTypeShorthandRoot(
hideOptional = false
): ReactNode {
const unwrapped = unwrapReference(shape, types);
const typeShorthand = renderTypeShorthand(unwrapped.shape, {}, types);
const typeShorthand = renderTypeShorthand(
unwrapped.shape,
{ nullable: unwrapped.isNullable },
types
);
return (
<span className="fern-api-property-meta">
<span>{typeShorthand}</span>
Expand Down Expand Up @@ -155,14 +159,18 @@ function toPrimitiveTypeLabelsString({

export function renderTypeShorthand(
shape: TypeShapeOrReference,
{ plural = false, withArticle = false }: TypeShorthandOptions = {
{
plural = false,
withArticle = false,
nullable = false,
}: TypeShorthandOptions = {
plural: false,
withArticle: false,
nullable: false,
},
types: Record<string, TypeDefinition>
): string {
const unwrapped = unwrapReference(shape, types);

const maybeWithArticle = (article: string, stringWithoutArticle: string) =>
withArticle ? `${article} ${stringWithoutArticle}` : stringWithoutArticle;

Expand All @@ -174,77 +182,82 @@ export function renderTypeShorthand(
return `${maybeWithArticle("an", "optional")} ${renderTypeShorthand(unwrapped.shape, { plural }, types)}`;
}

return visitDiscriminatedUnion(unwrapped.shape)._visit({
// primitives
primitive: (primitive) =>
visitDiscriminatedUnion(primitive.value, "type")._visit({
string: () => (plural ? "strings" : maybeWithArticle("a", "string")),
integer: () =>
plural ? "integers" : maybeWithArticle("an", "integer"),
uint: () => (plural ? "uints" : maybeWithArticle("a", "uint")),
uint64: () => (plural ? "uint64s" : maybeWithArticle("a", "uint64")),
double: () => (plural ? "doubles" : maybeWithArticle("a", "double")),
long: () => (plural ? "longs" : maybeWithArticle("a", "long")),
boolean: () => (plural ? "booleans" : maybeWithArticle("a", "boolean")),
datetime: () =>
plural ? "datetimes" : maybeWithArticle("a", "datetime"),
uuid: () => (plural ? "UUIDs" : maybeWithArticle("a", "UUID")),
base64: () =>
plural ? "Base64 strings" : maybeWithArticle("a", "Base64 string"),
date: () => (plural ? "dates" : maybeWithArticle("a", "date")),
bigInteger: () =>
plural ? "big integers" : maybeWithArticle("a", "big integer"),
_other: () => "<unknown>",
}),

// referenced shapes
object: () => (plural ? "objects" : maybeWithArticle("an", "object")),
undiscriminatedUnion: (union) => {
return uniq(
union.variants.map((variant) =>
renderTypeShorthand(variant.shape, { plural, withArticle }, types)
)
).join(" or ");
},
discriminatedUnion: () =>
plural ? "objects" : maybeWithArticle("an", "object"),
enum: (enumValue) => {
// if there are only 1 or 2 values, we can list them like literals (e.g. "apple" or "banana")
if (enumValue.values.length > 0 && enumValue.values.length < 3) {
return enumValue.values.map((value) => `"${value.value}"`).join(" or ");
}
return plural ? "enums" : maybeWithArticle("an", "enum");
},

// containing shapes
list: (list) =>
`${plural ? "lists of" : maybeWithArticle("a", "list of")} ${renderTypeShorthand(
list.itemShape,
{ plural: true },
types
)}`,
set: (set) =>
`${plural ? "sets of" : maybeWithArticle("a", "set of")} ${renderTypeShorthand(
set.itemShape,
{ plural: true },
types
)}`,
map: (map) =>
`${plural ? "maps from" : maybeWithArticle("a", "map from")} ${renderTypeShorthand(
map.keyShape,
{ plural: true },
types
)} to ${renderTypeShorthand(map.valueShape, { plural: true }, types)}`,

// literals
literal: (literal) =>
visitDiscriminatedUnion(literal.value, "type")._visit({
stringLiteral: ({ value }) => `"${value}"`,
booleanLiteral: ({ value }) => value.toString(),
_other: () => "<unknown>",
}),
// other
unknown: (value) => value.displayName ?? "any",
_other: () => "<unknown>",
});
return (
visitDiscriminatedUnion(unwrapped.shape)._visit({
// primitives
primitive: (primitive) =>
visitDiscriminatedUnion(primitive.value, "type")._visit({
string: () => (plural ? "strings" : maybeWithArticle("a", "string")),
integer: () =>
plural ? "integers" : maybeWithArticle("an", "integer"),
uint: () => (plural ? "uints" : maybeWithArticle("a", "uint")),
uint64: () => (plural ? "uint64s" : maybeWithArticle("a", "uint64")),
double: () => (plural ? "doubles" : maybeWithArticle("a", "double")),
long: () => (plural ? "longs" : maybeWithArticle("a", "long")),
boolean: () =>
plural ? "booleans" : maybeWithArticle("a", "boolean"),
datetime: () =>
plural ? "datetimes" : maybeWithArticle("a", "datetime"),
uuid: () => (plural ? "UUIDs" : maybeWithArticle("a", "UUID")),
base64: () =>
plural ? "Base64 strings" : maybeWithArticle("a", "Base64 string"),
date: () => (plural ? "dates" : maybeWithArticle("a", "date")),
bigInteger: () =>
plural ? "big integers" : maybeWithArticle("a", "big integer"),
_other: () => "<unknown>",
}),

// referenced shapes
object: () => (plural ? "objects" : maybeWithArticle("an", "object")),
undiscriminatedUnion: (union) => {
return uniq(
union.variants.map((variant) =>
renderTypeShorthand(variant.shape, { plural, withArticle }, types)
)
).join(" or ");
},
discriminatedUnion: () =>
plural ? "objects" : maybeWithArticle("an", "object"),
enum: (enumValue) => {
// if there are only 1 or 2 values, we can list them like literals (e.g. "apple" or "banana")
if (enumValue.values.length > 0 && enumValue.values.length < 3) {
return enumValue.values
.map((value) => `"${value.value}"`)
.join(" or ");
}
return plural ? "enums" : maybeWithArticle("an", "enum");
},

// containing shapes
list: (list) =>
`${plural ? "lists of" : maybeWithArticle("a", "list of")} ${renderTypeShorthand(
list.itemShape,
{ plural: true },
types
)}`,
set: (set) =>
`${plural ? "sets of" : maybeWithArticle("a", "set of")} ${renderTypeShorthand(
set.itemShape,
{ plural: true },
types
)}`,
map: (map) =>
`${plural ? "maps from" : maybeWithArticle("a", "map from")} ${renderTypeShorthand(
map.keyShape,
{ plural: true },
types
)} to ${renderTypeShorthand(map.valueShape, { plural: true }, types)}`,

// literals
literal: (literal) =>
visitDiscriminatedUnion(literal.value, "type")._visit({
stringLiteral: ({ value }) => `"${value}"`,
booleanLiteral: ({ value }) => value.toString(),
_other: () => "<unknown>",
}),
// other
unknown: (value) => value.displayName ?? "any",
_other: () => "<unknown>",
}) + (nullable ? " or null" : "")
);
}

0 comments on commit 530833a

Please sign in to comment.