Skip to content

Commit

Permalink
Generate correct code for empty enums (#176)
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickszmucer authored Sep 17, 2021
1 parent 67dbf16 commit 9ada1fd
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 23 deletions.
5 changes: 5 additions & 0 deletions changelog/@unreleased/pr-176.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: fix
fix:
description: Fix a regression introduced in https://github.com/palantir/conjure-typescript/pull/170 that resulted in generated code being incorrect for empty enums.
links:
- https://github.com/palantir/conjure-typescript/pull/176
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ types:
alias: binary
BinaryAliasTwo:
alias: BinaryAliasOne
EmptyEnum:
values: []
ExternalLongAliasOne:
alias: ExternalLong
ExternalLongAliasTwo:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const EmptyEnum = {};

export type EmptyEnum = void;
71 changes: 48 additions & 23 deletions src/commands/generate/typeGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,32 +66,57 @@ export function generateType(
export async function generateEnum(definition: IEnumDefinition, simpleAst: SimpleAst): Promise<void> {
const sourceFile = simpleAst.createSourceFile(definition.typeName);

const namespaceDefinition = sourceFile.addNamespace({
isExported: true,
name: definition.typeName.name,
typeAliases: definition.values.map(enumValue => ({
if (definition.values.length > 0) {
const namespaceDefinition = sourceFile.addNamespace({
isExported: true,
name: enumValue.value,
type: doubleQuote(enumValue.value),
docs: addDeprecatedToDocs(enumValue),
})),
bodyText: writer => {
definition.values.forEach(({ value }) => {
const quotedValue = doubleQuote(value);
writer.writeLine(`export const ${value} = ${quotedValue} as ${quotedValue};`);
});
},
});
if (definition.docs != null) {
namespaceDefinition.addJsDoc(definition.docs);
name: definition.typeName.name,
typeAliases: definition.values.map(enumValue => ({
isExported: true,
name: enumValue.value,
type: doubleQuote(enumValue.value),
docs: addDeprecatedToDocs(enumValue),
})),
bodyText: writer => {
definition.values.forEach(({ value }) => {
const quotedValue = doubleQuote(value);
writer.writeLine(`export const ${value} = ${quotedValue} as ${quotedValue};`);
});
},
});
if (definition.docs != null) {
namespaceDefinition.addJsDoc(definition.docs);
}
sourceFile.addTypeAlias({
isExported: true,
name: definition.typeName.name,
type: `keyof typeof ${definition.typeName.name}`,
});
} else {
// We need to special case empty enums for two reasons:
// 1) `keyof typeof MyEnum` results in an erorr
// 2) Typescript won't generate `const MyEnum = {}` and will instead just skip it from the compiled code.
const variableStatement = sourceFile.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
declarations: [
{
initializer: "{}",
name: definition.typeName.name,
},
],
isExported: true,
});
if (definition.docs != null) {
variableStatement.addJsDoc(definition.docs);
}
sourceFile.addTypeAlias({
isExported: true,
name: definition.typeName.name,
// We use void instead of never because void can't be assigned to anything else
// (while never is assignable to anything)
type: "void",
});
}

sourceFile.addTypeAlias({
isExported: true,
name: definition.typeName.name,
type: `keyof typeof ${definition.typeName.name}`,
});

sourceFile.formatText();
return sourceFile.save();
}
Expand Down

0 comments on commit 9ada1fd

Please sign in to comment.