From 8b2fcc53b1cfdc3b48e42499cc14c53d6b91db0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85smund=20Grammeltvedt?= Date: Wed, 24 Apr 2019 15:39:52 +0200 Subject: [PATCH 1/4] Ignore const assertions These are not normal type assertions and asserting that literal objects are immutable is a normal usage pattern. --- src/rules/noObjectLiteralTypeAssertionRule.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/rules/noObjectLiteralTypeAssertionRule.ts b/src/rules/noObjectLiteralTypeAssertionRule.ts index 2db26eb09da..20fafda71c9 100644 --- a/src/rules/noObjectLiteralTypeAssertionRule.ts +++ b/src/rules/noObjectLiteralTypeAssertionRule.ts @@ -86,6 +86,12 @@ function walk(ctx: Lint.WalkContext): void { if ( isAssertionExpression(node) && node.type.kind !== ts.SyntaxKind.AnyKeyword && + // If using TS >=3.4, allow const assertions + !( + (ts as any).isConstTypeReference && + node.type.kind === ts.SyntaxKind.TypeReference && + (ts as any).isConstTypeReference(node.type) + ) && // Compare with UnknownKeyword if using TS 3.0 or above (!!(ts.SyntaxKind as any).UnknownKeyword ? node.type.kind !== (ts.SyntaxKind as any).UnknownKeyword From 21afb1ee0b31506f50236a37dacc4bca6c265452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85smund=20Grammeltvedt?= Date: Thu, 25 Apr 2019 10:13:27 +0200 Subject: [PATCH 2/4] Bump typescript to get utility function for const assert --- package.json | 2 +- src/rules/noObjectLiteralTypeAssertionRule.ts | 4 ++-- .../no-object-literal-type-assertion/default/test.ts.lint | 4 ++++ yarn.lock | 8 ++++---- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 4f387121a59..a37ddf25ab2 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "tslint-config-prettier": "^1.18.0", "tslint-plugin-prettier": "^2.0.1", "tslint-test-config-non-relative": "file:test/external/tslint-test-config-non-relative", - "typescript": "~3.1.6", + "typescript": "~3.4.0", "yarn-deduplicate": "^1.1.1" }, "engines": { diff --git a/src/rules/noObjectLiteralTypeAssertionRule.ts b/src/rules/noObjectLiteralTypeAssertionRule.ts index 20fafda71c9..e2f89107174 100644 --- a/src/rules/noObjectLiteralTypeAssertionRule.ts +++ b/src/rules/noObjectLiteralTypeAssertionRule.ts @@ -88,9 +88,9 @@ function walk(ctx: Lint.WalkContext): void { node.type.kind !== ts.SyntaxKind.AnyKeyword && // If using TS >=3.4, allow const assertions !( - (ts as any).isConstTypeReference && node.type.kind === ts.SyntaxKind.TypeReference && - (ts as any).isConstTypeReference(node.type) + ts.isConstTypeReference !== undefined && + ts.isConstTypeReference(node.type) ) && // Compare with UnknownKeyword if using TS 3.0 or above (!!(ts.SyntaxKind as any).UnknownKeyword diff --git a/test/rules/no-object-literal-type-assertion/default/test.ts.lint b/test/rules/no-object-literal-type-assertion/default/test.ts.lint index eaebb211673..c66af9905b8 100644 --- a/test/rules/no-object-literal-type-assertion/default/test.ts.lint +++ b/test/rules/no-object-literal-type-assertion/default/test.ts.lint @@ -16,6 +16,10 @@ x as T; {} as unknown; {}; +// Allow const assertion +({}) as const; + ({}); + foo({} as T); ~~~~~~~ [0] diff --git a/yarn.lock b/yarn.lock index d97ba9dd553..9f9165d00d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1851,10 +1851,10 @@ type-detect@^1.0.0: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" integrity sha1-diIXzAbbJY7EiQihKY6LlRIejqI= -typescript@~3.1.6: - version "3.1.6" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.6.tgz#b6543a83cfc8c2befb3f4c8fba6896f5b0c9be68" - integrity sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA== +typescript@~3.4.0: + version "3.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99" + integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw== uglify-js@^3.1.4: version "3.5.4" From 8670ee4126f45bb6843e2f053965f1cab5f7552f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85smund=20Grammeltvedt?= Date: Thu, 25 Apr 2019 10:54:09 +0200 Subject: [PATCH 3/4] Make sure tests pass on older typescripts --- src/rules/noObjectLiteralTypeAssertionRule.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/rules/noObjectLiteralTypeAssertionRule.ts b/src/rules/noObjectLiteralTypeAssertionRule.ts index e2f89107174..ceec927c214 100644 --- a/src/rules/noObjectLiteralTypeAssertionRule.ts +++ b/src/rules/noObjectLiteralTypeAssertionRule.ts @@ -86,11 +86,12 @@ function walk(ctx: Lint.WalkContext): void { if ( isAssertionExpression(node) && node.type.kind !== ts.SyntaxKind.AnyKeyword && - // If using TS >=3.4, allow const assertions + // Allow const assertions, introduced in TS 3.4 !( node.type.kind === ts.SyntaxKind.TypeReference && - ts.isConstTypeReference !== undefined && - ts.isConstTypeReference(node.type) + (ts.isConstTypeReference !== undefined + ? ts.isConstTypeReference(node.type) + : node.type.getText(ctx.sourceFile) === "const") ) && // Compare with UnknownKeyword if using TS 3.0 or above (!!(ts.SyntaxKind as any).UnknownKeyword From 46886ece6127be590e7afbb4507a457a1ed92176 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85smund=20Grammeltvedt?= Date: Mon, 6 May 2019 11:42:31 +0200 Subject: [PATCH 4/4] Clean up tests and doc --- src/rules/noObjectLiteralTypeAssertionRule.ts | 11 ++++------- .../default/test.ts.lint | 2 ++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/rules/noObjectLiteralTypeAssertionRule.ts b/src/rules/noObjectLiteralTypeAssertionRule.ts index ceec927c214..46e0145059b 100644 --- a/src/rules/noObjectLiteralTypeAssertionRule.ts +++ b/src/rules/noObjectLiteralTypeAssertionRule.ts @@ -48,7 +48,9 @@ export class Rule extends Lint.Rules.AbstractRule { The type assertion in the latter case is either unnecessary or hides an error. The compiler will warn for excess properties with this syntax, but not missing required fields. For example: \`const x: { foo: number } = {}\` will fail to compile, but - \`const x = {} as { foo: number }\` will succeed.`, + \`const x = {} as { foo: number }\` will succeed. + Additionally, the const assertion \`const x = { foo: 1 } as const\`, + introduced in TypeScript 3.4, is considered beneficial and is ignored by this rule.`, optionsDescription: Lint.Utils.dedent` One option may be configured: @@ -87,12 +89,7 @@ function walk(ctx: Lint.WalkContext): void { isAssertionExpression(node) && node.type.kind !== ts.SyntaxKind.AnyKeyword && // Allow const assertions, introduced in TS 3.4 - !( - node.type.kind === ts.SyntaxKind.TypeReference && - (ts.isConstTypeReference !== undefined - ? ts.isConstTypeReference(node.type) - : node.type.getText(ctx.sourceFile) === "const") - ) && + !(ts.isConstTypeReference !== undefined && ts.isConstTypeReference(node.type)) && // Compare with UnknownKeyword if using TS 3.0 or above (!!(ts.SyntaxKind as any).UnknownKeyword ? node.type.kind !== (ts.SyntaxKind as any).UnknownKeyword diff --git a/test/rules/no-object-literal-type-assertion/default/test.ts.lint b/test/rules/no-object-literal-type-assertion/default/test.ts.lint index c66af9905b8..53a555a4710 100644 --- a/test/rules/no-object-literal-type-assertion/default/test.ts.lint +++ b/test/rules/no-object-literal-type-assertion/default/test.ts.lint @@ -16,9 +16,11 @@ x as T; {} as unknown; {}; +#if typescript >= 3.4.0 // Allow const assertion ({}) as const; ({}); +#endif foo({} as T); ~~~~~~~ [0]