Skip to content

Commit 978ebd6

Browse files
committed
fix: spread assignments
1 parent 0c53697 commit 978ebd6

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

packages/cli/src/metadataGeneration/initializer-value.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Tsoa } from '@tsoa/runtime';
44
const hasInitializer = (node: ts.Node): node is ts.HasInitializer => Object.prototype.hasOwnProperty.call(node, 'initializer');
55
const extractInitializer = (decl?: ts.Declaration) => (decl && hasInitializer(decl) && (decl.initializer as ts.Expression)) || undefined;
66
const extractImportSpecifier = (symbol?: ts.Symbol) => (symbol?.declarations && symbol.declarations.length > 0 && ts.isImportSpecifier(symbol.declarations[0]) && symbol.declarations[0]) || undefined;
7+
const isIterable = (obj: any): obj is Iterable<any> => obj != null && typeof obj[Symbol.iterator] === 'function';
78

89
export type InitializerValue = string | number | boolean | undefined | null | InitializerValue[];
910
export type DefinedInitializerValue = string | number | boolean | null | DefinedInitializerValue[];
@@ -23,7 +24,19 @@ export function getInitializerValue(initializer?: ts.Expression | ts.ImportSpeci
2324
switch (initializer.kind) {
2425
case ts.SyntaxKind.ArrayLiteralExpression: {
2526
const arrayLiteral = initializer as ts.ArrayLiteralExpression;
26-
return arrayLiteral.elements.map(element => getInitializerValue(element, typeChecker));
27+
return arrayLiteral.elements.reduce((acc, element) => {
28+
if (ts.isSpreadElement(element)) {
29+
const spreadValue = getInitializerValue(element.expression, typeChecker);
30+
if (spreadValue && isIterable(spreadValue)) {
31+
return acc.concat(...spreadValue);
32+
} else {
33+
throw new Error(`${typeof spreadValue} is not iterable`);
34+
}
35+
} else {
36+
acc.push(getInitializerValue(element, typeChecker));
37+
}
38+
return acc;
39+
}, [] as InitializerValue[]);
2740
}
2841
case ts.SyntaxKind.StringLiteral:
2942
case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
@@ -73,7 +86,18 @@ export function getInitializerValue(initializer?: ts.Expression | ts.ImportSpeci
7386
const objectLiteral = initializer as ts.ObjectLiteralExpression;
7487
const nestedObject: any = {};
7588
objectLiteral.properties.forEach((p: any) => {
76-
nestedObject[p.name.text] = getInitializerValue(p.initializer, typeChecker);
89+
if (ts.isSpreadAssignment(p)) {
90+
const spreadValue = getInitializerValue(p.expression, typeChecker);
91+
if (spreadValue) {
92+
if (typeof spreadValue === 'object') {
93+
Object.assign(nestedObject, spreadValue);
94+
} else {
95+
throw new Error(`Spread types may only be created from object types.`);
96+
}
97+
}
98+
} else {
99+
nestedObject[p.name.text] = getInitializerValue(p.initializer, typeChecker);
100+
}
77101
});
78102
return nestedObject;
79103
}

0 commit comments

Comments
 (0)