From 9c36201a3f0dcfe04e6b4d77939b8a94ca14e773 Mon Sep 17 00:00:00 2001 From: YeonJuan Date: Mon, 24 Feb 2025 23:25:51 +0900 Subject: [PATCH 1/3] fix(eslint-plugin): [no-unnecessary-type-assertion] handle unknown --- .../rules/no-unnecessary-type-assertion.ts | 10 +++++ .../no-unnecessary-type-assertion.test.ts | 44 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts index 83c8afe9b78c..526e2449b999 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts @@ -349,6 +349,16 @@ export default createRule({ const contextualType = getContextualType(checker, originalNode); if (contextualType) { + const typeIsUnknown = isTypeFlagSet(type, ts.TypeFlags.Unknown); + const contextualTypeIsUnknown = isTypeFlagSet( + contextualType, + ts.TypeFlags.Unknown, + ); + + if (typeIsUnknown && !contextualTypeIsUnknown) { + return; + } + // in strict mode you can't assign null to undefined, so we have to make sure that // the two types share a nullable type const typeIncludesUndefined = isTypeFlagSet( diff --git a/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts b/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts index 1ef1a3dfb371..c711d9b14d38 100644 --- a/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts @@ -416,6 +416,18 @@ enum T { const b = 1 as T.Value2; `, }, + ` +const foo: unknown = {}; +const bar: object = foo!; +const baz: {} = foo!; + `, + ` +function foo(bar: T) { + return {} as T; +} +const baz: unknown = {} +foo(baz!); + `, ], invalid: [ @@ -1335,5 +1347,37 @@ declare const a: T.Value1; const b = a; `, }, + { + code: ` +const foo: unknown = {}; +const bar: unknown = foo!; + `, + errors: [ + { + messageId: 'contextuallyUnnecessary', + }, + ], + output: ` +const foo: unknown = {}; +const bar: unknown = foo; + `, + }, + { + code: ` +function foo(bar: unknown) {} +const baz: unknown = {}; +foo(baz!); + `, + errors: [ + { + messageId: 'contextuallyUnnecessary', + }, + ], + output: ` +function foo(bar: unknown) {} +const baz: unknown = {}; +foo(baz); + `, + }, ], }); From 437b7f93b11cdbdbb6f1e4691c901d165af7129f Mon Sep 17 00:00:00 2001 From: YeonJuan Date: Mon, 24 Feb 2025 23:33:34 +0900 Subject: [PATCH 2/3] fix format --- .../tests/rules/no-unnecessary-type-assertion.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts b/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts index c711d9b14d38..b9660ad79f73 100644 --- a/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts @@ -425,7 +425,7 @@ const baz: {} = foo!; function foo(bar: T) { return {} as T; } -const baz: unknown = {} +const baz: unknown = {}; foo(baz!); `, ], From f6100800e53cfb53dda5a17dc62a09fa69cf147f Mon Sep 17 00:00:00 2001 From: YeonJuan Date: Mon, 3 Mar 2025 20:48:14 +0900 Subject: [PATCH 3/3] apply reviews --- .../src/rules/no-unnecessary-type-assertion.ts | 11 ++++------- .../tests/rules/no-unnecessary-type-assertion.test.ts | 9 +++++---- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts index 526e2449b999..4e26d6e20aa2 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts @@ -349,13 +349,10 @@ export default createRule({ const contextualType = getContextualType(checker, originalNode); if (contextualType) { - const typeIsUnknown = isTypeFlagSet(type, ts.TypeFlags.Unknown); - const contextualTypeIsUnknown = isTypeFlagSet( - contextualType, - ts.TypeFlags.Unknown, - ); - - if (typeIsUnknown && !contextualTypeIsUnknown) { + if ( + isTypeFlagSet(type, ts.TypeFlags.Unknown) && + !isTypeFlagSet(contextualType, ts.TypeFlags.Unknown) + ) { return; } diff --git a/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts b/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts index b9660ad79f73..c28260e79b4a 100644 --- a/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts @@ -418,13 +418,14 @@ const b = 1 as T.Value2; }, ` const foo: unknown = {}; -const bar: object = foo!; const baz: {} = foo!; `, ` -function foo(bar: T) { - return {} as T; -} +const foo: unknown = {}; +const bar: object = foo!; + `, + ` +declare function foo(bar: T): T; const baz: unknown = {}; foo(baz!); `,