feat(typescript-angular): update enum definitions to use 'as const' for improved type safety (#20958)

fixes #20809
This commit is contained in:
Daniel Schreiber 2025-03-24 17:46:04 +01:00 committed by GitHub
parent 07e5a674db
commit 16552755bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 173 additions and 148 deletions

View File

@ -13,8 +13,6 @@ export enum {{classname}} {
} }
{{/stringEnums}} {{/stringEnums}}
{{^stringEnums}} {{^stringEnums}}
export type {{classname}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
export const {{classname}} = { export const {{classname}} = {
{{#allowableValues}} {{#allowableValues}}
{{#enumVars}} {{#enumVars}}
@ -22,9 +20,11 @@ export const {{classname}} = {
/** /**
* {{.}} * {{.}}
*/{{/enumDescription}} */
{{name}}: {{{value}}} as {{classname}}{{^-last}},{{/-last}} {{/enumDescription}}
{{name}}: {{{value}}}{{^-last}},{{/-last}}
{{/enumVars}} {{/enumVars}}
{{/allowableValues}} {{/allowableValues}}
}; } as const;
export type {{classname}} = typeof {{classname}}[keyof typeof {{classname}}];
{{/stringEnums}} {{/stringEnums}}

View File

@ -15,14 +15,14 @@ export enum {{classname}}{{enumName}} {
}; };
{{/stringEnums}} {{/stringEnums}}
{{^stringEnums}} {{^stringEnums}}
export type {{enumName}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
export const {{enumName}} = { export const {{enumName}} = {
{{#allowableValues}} {{#allowableValues}}
{{#enumVars}} {{#enumVars}}
{{name}}: {{{value}}} as {{enumName}}{{^-last}},{{/-last}} {{name}}: {{{value}}}{{^-last}},{{/-last}}
{{/enumVars}} {{/enumVars}}
{{/allowableValues}} {{/allowableValues}}
}; } as const;
export type {{enumName}} = typeof {{enumName}}[keyof typeof {{enumName}}];
{{/stringEnums}} {{/stringEnums}}
{{/isEnum}} {{/isEnum}}
{{/vars}} {{/vars}}

View File

@ -439,4 +439,29 @@ public class TypeScriptAngularClientCodegenTest {
final String fileContents = Files.readString(Paths.get(output + "/api.base.service.ts")); final String fileContents = Files.readString(Paths.get(output + "/api.base.service.ts"));
assertThat(fileContents).containsOnlyOnce("basePath = '/relative/url'"); assertThat(fileContents).containsOnlyOnce("basePath = '/relative/url'");
} }
@Test
public void testEnumAsConst() throws IOException {
// GIVEN
final String specPath = "src/test/resources/3_0/enum.yaml";
File output = Files.createTempDirectory("test").toFile();
output.deleteOnExit();
// WHEN
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("typescript-angular")
.setInputSpec(specPath)
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
Generator generator = new DefaultGenerator();
generator.opts(clientOptInput).generate();
// THEN
final String fileContents = Files.readString(Paths.get(output + "/model/type.ts"));
assertThat(fileContents).containsOnlyOnce("} as const;");
assertThat(fileContents).doesNotContain(" as Type");
}
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -26,12 +26,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -26,12 +26,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -26,12 +26,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -26,12 +26,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -27,12 +27,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -27,12 +27,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -27,12 +27,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -27,12 +27,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -27,12 +27,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
SHIPPED: 'delivered' as StatusEnum SHIPPED: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -27,12 +27,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -27,12 +27,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -27,12 +27,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -27,12 +27,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -24,12 +24,12 @@ export interface Order {
complete?: boolean; complete?: boolean;
} }
export namespace Order { export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = { export const StatusEnum = {
Placed: 'placed' as StatusEnum, Placed: 'placed',
Approved: 'approved' as StatusEnum, Approved: 'approved',
Delivered: 'delivered' as StatusEnum Delivered: 'delivered'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }

View File

@ -27,12 +27,12 @@ export interface Pet {
status?: Pet.StatusEnum; status?: Pet.StatusEnum;
} }
export namespace Pet { export namespace Pet {
export type StatusEnum = 'available' | 'pending' | 'sold';
export const StatusEnum = { export const StatusEnum = {
Available: 'available' as StatusEnum, Available: 'available',
Pending: 'pending' as StatusEnum, Pending: 'pending',
Sold: 'sold' as StatusEnum Sold: 'sold'
}; } as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
} }