Skip to content

Commit 9cbf1a6

Browse files
committed
fix: union type display for string intersections
1 parent 9d3c8e6 commit 9cbf1a6

File tree

1 file changed

+31
-4
lines changed

1 file changed

+31
-4
lines changed

src/components/object-definition.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,25 @@ export function getObjectDefinition(
8686
return { type };
8787
}
8888

89-
function getPrimitiveType(type: ts.UnionOrIntersectionType) {
90-
if (type.types.every(subtype => subtype.isStringLiteral() || subtype.flags & ts.TypeFlags.StringLiteral)) {
89+
function isStringLiteralOrStringIntersection(subtype: ts.Type, checker: ts.TypeChecker): boolean {
90+
// Check if it's a string literal
91+
if (subtype.isStringLiteral() || subtype.flags & ts.TypeFlags.StringLiteral) {
92+
return true;
93+
}
94+
// Check if it's an intersection type that represents "string & something"
95+
// This pattern is used to allow custom strings while providing autocomplete for known literals
96+
if (subtype.isIntersection()) {
97+
const stringified = stringifyType(subtype, checker);
98+
// Match patterns like "string & { _?: undefined; }" or similar
99+
if (stringified.startsWith('string &')) {
100+
return true;
101+
}
102+
}
103+
return false;
104+
}
105+
106+
function getPrimitiveType(type: ts.UnionOrIntersectionType, checker: ts.TypeChecker) {
107+
if (type.types.every(subtype => isStringLiteralOrStringIntersection(subtype, checker))) {
91108
return 'string';
92109
}
93110
if (type.types.every(subtype => subtype.isNumberLiteral() || subtype.flags & ts.TypeFlags.NumberLiteral)) {
@@ -103,9 +120,19 @@ function getUnionTypeDefinition(
103120
checker: ts.TypeChecker
104121
): { type: string; inlineType: UnionTypeDefinition } {
105122
const valueDescriptions = extractValueDescriptions(realType, typeNode);
106-
const primitiveType = getPrimitiveType(realType);
123+
const primitiveType = getPrimitiveType(realType, checker);
107124
const values = realType.types.map(subtype => {
108-
if (primitiveType && subtype.isStringLiteral()) {
125+
if (primitiveType === 'string') {
126+
if (subtype.isStringLiteral()) {
127+
return (subtype as ts.LiteralType).value.toString();
128+
}
129+
// For intersection types like "string & { _?: undefined; }", return "string"
130+
// This indicates that custom string values are allowed
131+
if (subtype.isIntersection()) {
132+
return 'string';
133+
}
134+
}
135+
if (primitiveType === 'number' && subtype.isNumberLiteral()) {
109136
return (subtype as ts.LiteralType).value.toString();
110137
}
111138
return stringifyType(subtype, checker);

0 commit comments

Comments
 (0)