When your code is accurate, but the Typescript type-checking algorithm fails to recognize it, you have two choices: either refactor the code to align with Typescript's expectations or instruct Typescript to overlook that specific section of the code.
Typically, the former option is preferred because if you modify the code later on, you would want Typescript to verify that the changes didn't cause any issues. Based on how you phrased your query ("I just want to gloss over a bit of type checking"), it seems like you might lean towards the latter approach in this scenario.
Making it Type-Check
To ensure this code passes type-checking, you need to specify that the items within array
are either of type 'foo'
or {bar: 'quz'}
. This way, when you confirm that it
is not 'foo'
, control-flow type narrowing occurs, narrowing the type of it
to {bar: 'quz'}
within the if
block.
const array: ('foo' | {bar: 'quz'})[] = ['foo', {bar: 'quz'}];
Naturally, providing such a type annotation may seem redundant as the information can be inferred from the array itself if you use as const
:
const array = ['foo', {bar: 'quz'}] as const;
In both scenarios, you do not require anything special within the if
block to explicitly define that it
has a more specific type than before; Typescript handles type narrowing automatically.
If you wish to have all aspects of the code type-checked, then you must unequivocally inform Typescript that those two types are the only valid options somehow. Failing to do so will not imply one option by ruling out the other. Using as const
is the most straightforward method to achieve this.
Instructing Typescript to Skip Checking
If you desire to "gloss over" type-checking and instruct Typescript to refrain from scrutinizing a portion of your code, the easiest solution is to utilize any
:
array.forEach((it: any) => {
if (it !== "foo") {
it.bar; // no error
}
});
// or:
array.forEach((it) => {
if (it !== "foo") {
(it as any).bar; // no error
}
});
This is precisely what any
is intended for: disabling type-checking for the variable
it</code, whether across the entire function or for a single instance.</p>
<p>Other methods to bypass type-checking for certain parts of your code include:</p>
<ul>
<li>Using a type assertion with the stricter type (e.g., <code>(it as {bar: 'quz'}).bar
). Typescript performs a minimal check to ensure your assertion isn't nonsensical, relying on your judgment for the correct type.
Implementing a user-defined type guard, which goes unchecked in the sense that Typescript doesn't confirm if your function returns false</code when the argument isn't the expected type.</li>
<li>Utilizing an <a href="http://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions" rel="nofollow noreferrer">assertion function</a> similar to @jcalz's comment, where Typescript doesn't verify if your function throws an error when the argument isn't the correct type.</li>
</ul>
<p>Although these alternatives provide greater safety than <code>any
, they do require more code to implement, making them less suitable if conciseness is a priority for you.