Skip to content

Commit 5e6a919

Browse files
committed
fix(typescript): Handle invalid type names
1 parent 5028056 commit 5e6a919

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed

plugins/typescript/src/core/schemaToTypeAliasDeclaration.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,30 @@ describe("schemaToTypeAliasDeclaration", () => {
946946
`);
947947
});
948948

949+
it("should generate valid identifier from number name", () => {
950+
const schema: SchemaObject = {};
951+
952+
expect(printSchema(schema, "200")).toMatchInlineSnapshot(`
953+
"export type _200 = void;"
954+
`);
955+
});
956+
957+
it("should generate valid identifier from symbol name", () => {
958+
const schema: SchemaObject = {};
959+
960+
expect(printSchema(schema, "-")).toMatchInlineSnapshot(`
961+
"export type _ = void;"
962+
`);
963+
});
964+
965+
it("should generate valid identifier from invalid name", () => {
966+
const schema: SchemaObject = {};
967+
968+
expect(printSchema(schema, "🙂")).toMatchInlineSnapshot(`
969+
"export type _ = void;"
970+
`);
971+
});
972+
949973
it("should generate a `never` if the combined type is broken", () => {
950974
const schema: SchemaObject = {
951975
allOf: [{ type: "string" }, { type: "number" }],

plugins/typescript/src/core/schemaToTypeAliasDeclaration.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from "openapi3-ts/oas30";
1212
import { singular } from "pluralize";
1313
import { isValidIdentifier } from "tsutils";
14-
import ts, { factory as f } from "typescript";
14+
import ts, { factory as f, isIdentifierStart } from "typescript";
1515
import { getReferenceSchema } from "./getReference";
1616

1717
type RemoveIndex<T> = {
@@ -56,11 +56,24 @@ export const schemaToTypeAliasDeclaration = (
5656
const jsDocNode = isSchemaObject(schema)
5757
? getJSDocComment(schema, context)
5858
: undefined;
59+
60+
let identifier = pascal(name);
61+
62+
// If the identifier does not start with a valid character, prefix it with an underscore.
63+
if (!isIdentifierStart(identifier.charCodeAt(0), ts.ScriptTarget.Latest)) {
64+
identifier = `_${identifier}`;
65+
}
66+
67+
// If the identifier is still not valid, remove invalid characters.
68+
if (!isValidIdentifier(identifier)) {
69+
identifier = identifier.replace(/[^a-zA-Z0-9_]/g, "");
70+
}
71+
5972
const declarationNode = f.createTypeAliasDeclaration(
6073
[f.createModifier(ts.SyntaxKind.ExportKeyword)],
61-
pascal(name),
74+
identifier,
6275
undefined,
63-
getType(schema, context, name)
76+
getType(schema, context, identifier)
6477
);
6578

6679
return jsDocNode ? [jsDocNode, declarationNode] : [declarationNode];
@@ -89,10 +102,10 @@ export const getType = (
89102

90103
let refNode: ts.TypeNode = f.createTypeReferenceNode(
91104
namespace === context.currentComponent
92-
? f.createIdentifier(pascal(name))
105+
? f.createIdentifier(name)
93106
: f.createQualifiedName(
94107
f.createIdentifier(pascal(namespace)),
95-
f.createIdentifier(pascal(name))
108+
f.createIdentifier(name)
96109
)
97110
);
98111

@@ -173,7 +186,7 @@ export const getType = (
173186

174187
if (schema.enum) {
175188
if (isNodeEnum) {
176-
return f.createTypeReferenceNode(f.createIdentifier(pascal(name || "")));
189+
return f.createTypeReferenceNode(f.createIdentifier(name || ""));
177190
}
178191

179192
const unionTypes = f.createUnionTypeNode([

0 commit comments

Comments
 (0)