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}}
export type {{classname}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
export const {{classname}} = {
{{#allowableValues}}
{{#enumVars}}
@ -22,9 +20,11 @@ export const {{classname}} = {
/**
* {{.}}
*/{{/enumDescription}}
{{name}}: {{{value}}} as {{classname}}{{^-last}},{{/-last}}
*/
{{/enumDescription}}
{{name}}: {{{value}}}{{^-last}},{{/-last}}
{{/enumVars}}
{{/allowableValues}}
};
} as const;
export type {{classname}} = typeof {{classname}}[keyof typeof {{classname}}];
{{/stringEnums}}

View File

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

View File

@ -439,4 +439,29 @@ public class TypeScriptAngularClientCodegenTest {
final String fileContents = Files.readString(Paths.get(output + "/api.base.service.ts"));
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;
}
export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
export const StatusEnum = {
Placed: 'placed' as StatusEnum,
Approved: 'approved' as StatusEnum,
Delivered: 'delivered' as StatusEnum
};
Placed: 'placed',
Approved: 'approved',
Delivered: 'delivered'
} as const;
export type StatusEnum = typeof StatusEnum[keyof typeof StatusEnum];
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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