Typescript is great about type checking, but sometimes I know better than it does.
I'd like to be able to say "From this scope on, pretend variable x is of type y"
const array = ["foo", {bar: "quz"}];
array.forEach((it) => {
if (it !== "foo") {
declare it: {bar: "quz"}; // not real code, what I'd like to do
it.bar; // Error: Property 'bar' does not exist on type 'string | { bar: string; }'
}
});
isBarQuz(checkMe: any): checkMe is {bar: "quz"}
;const array = [...] as const
I don't want to do any of these things. I just want to gloss over a bit of type checking and get on with my work. How can I do this?
When your code is correct but Typescript's type-checking algorithm doesn't know that it's correct, you have two options: either rewrite the code in a way such that Typescript gets it right, or tell Typescript not to check that part of the code.
The former is usually preferred, because if you change the code later, you'd usually like Typescript to be able to check that you didn't make it stop working. From the wording of your question ( "I just want to gloss over a bit of type checking" ), it sounds like you might prefer the latter here.
To get this code to type-check, you need is to specify that the contents of array
are either of type 'foo'
, or they are of type {bar: 'quz'}
. Then when you test that it
is not 'foo'
, control-flow type narrowing occurs, and the type of it
is narrowed to {bar: 'quz'}
inside the if
block.
const array: ('foo' | {bar: 'quz'})[] = ['foo', {bar: 'quz'}];
Of course, writing such a type annotation means repeating yourself; the annotation doesn't say anything that can't be inferred from the array literal itself if you write as const
:
const array = ['foo', {bar: 'quz'}] as const;
Either way, you don't need anything special inside the if
block to explicitly declare that it
has a narrower type than it did before the if
block; Typescript narrows its type automatically.
If you want all of the code to be type-checked, then you must let Typescript know that those two types are the only options somehow, otherwise ruling out one option doesn't imply that it's the other option. as const
is the simplest way to do so.
If you want to "gloss over" type-checking in the sense of asking Typescript not to type-check part of your code, the simplest way is to use 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 the intended purpose of any
: it disables type-checking of the variable it
, either for the whole function or for a single use.
The other ways to disable type-checking for part of your code are to:
(it as {bar: 'quz'}).bar
). Typescript will do a very weak check to make sure your assertion isn't impossible, but otherwise it trusts that you have asserted the right type. false
when the argument isn't of the right type. These alternative options give you more safety than any
, but take more code to write, so they may be unsuitable if brevity is important for you.
const arr = ["foo", {bar: "quz"}];
arr.forEach((it) => {
if (it !== "foo") {
console.log((it as any).bar);// gives quz
});
Hope it helps
This doesn't work for const
variables or non union types, but it's quick and easy enough I can fill out the broad strokes on something before getting caught up in every feasible permutation.
You can reassign a variable to itself with a different type.
interface IBarQuz { bar: "quz" };
const barquz: IBarQuz = { bar: "quz" };
const array = ["foo", barquz];
array.forEach((it) => {
if (it !== "foo") {
it = it as IBarQuz
// alternate: it = it as typeof barquz;
it.bar;
}
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.