Repository: TypeScript
Issue: TS2352: Suggest narrowing via type guard
Labels: Suggestion,Awaiting More Feedback

# Suggestion

<!--
  Please fill in each section completely. Thank you!
-->

## 🔍 Search Terms

<!--
  💡 Did you know? TypeScript has over 2,000 open suggestions!
  🔎 Please search thoroughly before logging new feature requests as most common ideas already have a proposal in progress.
  The "Common Feature Requests" section of the FAQ lists many popular requests: https://github.com/Microsoft/TypeScript/wiki/FAQ#common-feature-requests

  Replace the text below:
-->

ts(2352), TS2352, neither type sufficiently overlaps, as unknown, instanceof, typeof, narrowing, type guard

[Google search: site:github.com/microsoft/TypeScript/issues ("ts(2352)" OR "TS2352" OR "neither type sufficiently overlaps" OR "as unknown") ("instanceof" OR "typeof" OR "narrowing" OR "type guard")](https://www.google.com/search?q=site%3Agithub.com%2Fmicrosoft%2FTypeScript%2Fissues+%28%22ts%282352%29%22+OR+%22TS2352%22+OR+%22neither+type+sufficiently+overlaps%22+OR+%22as+unknown%22%29+%28%22instanceof%22+OR+%22typeof%22+OR+%22narrowing%22+OR+%22type+guard%22%29)

## ✅ Viability Checklist

<!--
   Suggestions that don't meet all these criteria are very, very unlikely to be accepted.
   We always recommend reviewing the TypeScript design goals before investing time writing
   a proposal for ideas outside the scope of the project.
-->
My suggestion meets these guidelines:

* [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [x] This wouldn't change the runtime behavior of existing JavaScript code
* [x] This could be implemented without emitting different JS based on the types of the expressions
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).


## ⭐ Suggestion

[Diagnostic message ts(2352)](https://github.com/microsoft/TypeScript/blob/f6cf510/src/compiler/diagnosticMessages.json#L1815-L1817) (_Conversion of type '{0}' to type '{1}' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first._) should suggest [narrowing via type guard](https://www.typescriptlang.org/docs/handbook/2/narrowing.html) (`instanceof`, `typeof`). In scenarios where this is viable, it's much safer than `x as unknown as SomeType`. Ideally, this suggestion would only appear when applicable, e.g. when using `as` to narrow a type. In which case TS2352 would remain as-is, and a new diagnostic message would be created, to be shown when applicable.

## 📃 Motivating Example

Not sure this would be a "blog post" worthy change...

## 💻 Use Cases

While converting (from JS to TS) some code that I found on [Stack Overflow](https://stackoverflow.com/questions/2952667/find-all-css-rules-that-apply-to-an-element#37958301), I saw `TS2352` several times, in cases where I was attempting to use `as` to narrow DOM types, e.g:
- from `CSSStyleRule` to `CSSImportRule`
- from `CSSStyleRule` to `CSSMediaRule`

In these cases, using `instanceof` type guards is a much better solution (at least to the best of my knowledge), e.g.
- `if (x instanceof CSSImportRule)`
- `if (x instanceof CSSMediaRule)`

Presumably, it should be possible to look at a line like:
```ts
const x: CSSRule = foo.bar;
const y = x as CSSMediaRule;
```
... and then follow the chain of `extends` from `CSSMediaRule` to `CSSRule`:
```ts
interface CSSMediaRule extends CSSConditionRule {}
interface CSSConditionRule extends CSSGroupingRule {}
interface CSSGroupingRule extends CSSRule {}
```
(as per [v4.8.4/lib/lib.dom.d.ts#L2573-L2662](https://github.com/microsoft/TypeScript/blob/v4.8.4/lib/lib.dom.d.ts#L2573-L2662))

... but again, this may not be feasible to implement.