diff --git a/linter-4.2/src/TypeScriptLinter.ts b/linter-4.2/src/TypeScriptLinter.ts index 27442da9f6353270955b0c54de49988c6273e5b3..5651cbcfbfdc9a5bbbfcf52c6be5595215aff00c 100644 --- a/linter-4.2/src/TypeScriptLinter.ts +++ b/linter-4.2/src/TypeScriptLinter.ts @@ -693,20 +693,16 @@ export class TypeScriptLinter { ) { // We can use literals as property names only when creating Record or any interop instances. let isRecordObjectInitializer = false; - let isDynamicLiteralInitializer = false; + let isDynamic = false; if (ts.isPropertyAssignment(node)) { - let objectLiteralType = this.tsTypeChecker.getContextualType( - node.parent - ); - isRecordObjectInitializer = - !!objectLiteralType && - this.tsUtils.isStdRecordType(objectLiteralType); - isDynamicLiteralInitializer = this.tsUtils.isDynamicLiteralInitializer( - node.parent - ); + let objectLiteralType = this.tsTypeChecker.getContextualType(node.parent); + if (objectLiteralType) { + isRecordObjectInitializer = this.tsUtils.isStdRecordType(objectLiteralType); + isDynamic = this.tsUtils.isLibraryType(objectLiteralType) || this.tsUtils.isDynamicLiteralInitializer(node.parent); + } } - if (!isRecordObjectInitializer && !isDynamicLiteralInitializer) { + if (!isRecordObjectInitializer && !isDynamic) { let autofix: Autofix[] | undefined = Autofixer.fixLiteralAsPropertyName(node); let autofixable = autofix != undefined; diff --git a/linter-4.2/test/dynamic_lib.d.ts b/linter-4.2/test/dynamic_lib.d.ts index e3da589b5418ec259aa310a41fea0f454f17ede3..843931397eaf4c1fce6ff89f458826d49642771c 100644 --- a/linter-4.2/test/dynamic_lib.d.ts +++ b/linter-4.2/test/dynamic_lib.d.ts @@ -93,3 +93,7 @@ declare class B { } export declare function bad_func(): A & B; + +export type IndexedSignatureType = { + [key: string]: string; +} \ No newline at end of file diff --git a/linter-4.2/test/dynamic_object_literals.ts b/linter-4.2/test/dynamic_object_literals.ts index ea7f9759a2e8cf76d1eb0dd81536959bfcf1beeb..fae9413ea1d4ccb581327bddbdda25cb9c805912 100644 --- a/linter-4.2/test/dynamic_object_literals.ts +++ b/linter-4.2/test/dynamic_object_literals.ts @@ -24,7 +24,8 @@ import { dynamic_array, padding, margin, - position + position, + IndexedSignatureType } from "./dynamic_lib" function main(): void { @@ -84,4 +85,13 @@ dynamic_array.splice(2, 0, {a: 1, b: '2'}); // #13550 - allow literals as property names in dynamic context padding({'top': '0px', 'right': '5px', 'bottom': '10px', 'left': '15px'}); margin({'top': '10px', 'right': '20px', 'bottom': '30px', 'left': '40px'}); -position({'x': '20', 'y': '40'}); \ No newline at end of file +position({'x': '20', 'y': '40'}); + +// allow literal as property name for type aliases that come from interop +function typeAliasLitAsPropName(): IndexedSignatureType { + return { + 'a': '1', + 'b': '2', + 'c': '3' + } +} \ No newline at end of file diff --git a/linter/src/TypeScriptLinter.ts b/linter/src/TypeScriptLinter.ts index 15d018ed5999142bb38be27095e9792ba21f180b..039e904b8b8a0c53112a6ff265f987683adbef61 100644 --- a/linter/src/TypeScriptLinter.ts +++ b/linter/src/TypeScriptLinter.ts @@ -596,14 +596,16 @@ export class TypeScriptLinter { if (propName && (propName.kind === ts.SyntaxKind.NumericLiteral || propName.kind === ts.SyntaxKind.StringLiteral)) { // We can use literals as property names only when creating Record or any interop instances. let isRecordObjectInitializer = false; - let isDynamicLiteralInitializer = false; + let isDynamic = false; if (ts.isPropertyAssignment(node)) { let objectLiteralType = this.tsTypeChecker.getContextualType(node.parent); - isRecordObjectInitializer = !!objectLiteralType && this.tsUtils.isStdRecordType(objectLiteralType); - isDynamicLiteralInitializer = this.tsUtils.isDynamicLiteralInitializer(node.parent); + if (objectLiteralType) { + isRecordObjectInitializer = this.tsUtils.isStdRecordType(objectLiteralType); + isDynamic = this.tsUtils.isLibraryType(objectLiteralType) || this.tsUtils.isDynamicLiteralInitializer(node.parent); + } } - if (!isRecordObjectInitializer && !isDynamicLiteralInitializer) { + if (!isRecordObjectInitializer && !isDynamic) { let autofix : Autofix[] | undefined = Autofixer.fixLiteralAsPropertyName(node); let autofixable = autofix != undefined; if (!this.autofixesInfo.shouldAutofix(node, FaultID.LiteralAsPropertyName)) { diff --git a/linter/test/dynamic_lib.d.ts b/linter/test/dynamic_lib.d.ts index e3da589b5418ec259aa310a41fea0f454f17ede3..843931397eaf4c1fce6ff89f458826d49642771c 100644 --- a/linter/test/dynamic_lib.d.ts +++ b/linter/test/dynamic_lib.d.ts @@ -93,3 +93,7 @@ declare class B { } export declare function bad_func(): A & B; + +export type IndexedSignatureType = { + [key: string]: string; +} \ No newline at end of file diff --git a/linter/test/dynamic_object_literals.ts b/linter/test/dynamic_object_literals.ts index ea7f9759a2e8cf76d1eb0dd81536959bfcf1beeb..fae9413ea1d4ccb581327bddbdda25cb9c805912 100644 --- a/linter/test/dynamic_object_literals.ts +++ b/linter/test/dynamic_object_literals.ts @@ -24,7 +24,8 @@ import { dynamic_array, padding, margin, - position + position, + IndexedSignatureType } from "./dynamic_lib" function main(): void { @@ -84,4 +85,13 @@ dynamic_array.splice(2, 0, {a: 1, b: '2'}); // #13550 - allow literals as property names in dynamic context padding({'top': '0px', 'right': '5px', 'bottom': '10px', 'left': '15px'}); margin({'top': '10px', 'right': '20px', 'bottom': '30px', 'left': '40px'}); -position({'x': '20', 'y': '40'}); \ No newline at end of file +position({'x': '20', 'y': '40'}); + +// allow literal as property name for type aliases that come from interop +function typeAliasLitAsPropName(): IndexedSignatureType { + return { + 'a': '1', + 'b': '2', + 'c': '3' + } +} \ No newline at end of file