Here's a bit of code I was looking over (I'm new to TypeScript):
// Set up decorator
const proxy = Object.create(null) as ts.LanguageService;
const oldLS = info.languageService;
for (const k in oldLS) {
(<any>proxy)[k] = function () {
return (<any>oldLS)[k].apply(oldLS, arguments);
}
}
Look at this part of the code:
(<any>proxy)[k] = function () {
return (<any>oldLS)[k].apply(oldLS, arguments);
}
Why is casting needed on (<any>proxy)[k]
since aren't all objects accessible via the bracket notation? And furthermore, why is the above assignment not simply written as: (<any>proxy)[k] = (<any>oldLS)[k];
(what is this code trying to accomplish)?
They are using < > to pass the type parameters. So you decide to use the same. Don't let the < > intimidate you. It is just a way to pass types as arguments.
In Typescript, Type assertion is a technique that informs the compiler about the type of a variable. Type assertion is similar to typecasting but it doesn't reconstruct code. You can use type assertion to specify a value's type and tell the compiler not to deduce it.
❮ Previous Next ❯ There are times when working with types where it's necessary to override the type of a variable, such as when incorrect types are provided by a library. Casting is the process of overriding a type.
As you probably know, angle brackets in pairs are used: As a deprecated syntax for type-assertions. For manually specifying generic type parameters. For declaring elements in .
On the face of it, it sounds like you're asking us to explain why some unknown person might have performed a type assertion in some unspecified TypeScript code for some unspecified TypeScript version. Not sure how someone could really help you there.
But luckily the magic of search engines has divined that you're referring to this tutorial for writing your own language service plugin in TypeScript, written by @RyanCavanaugh.
The reason seems to be that the key k
is being inferred as string
, and not as keyof ts.LanguageService
, so the compiler rejects indexing into proxy
and oldLS
with k
, unless you do some sort of assertion.
I'm not exactly sure why this is happening; I think that since TypeScript v2.1.4, the variable a
in for a in b
should have the type keyof typeof b
.
For example:
function hmm<T>(t: T): void {
for (const k in t) { // k is inferred as keyof T
const keyofT: keyof T = k; // no error
}
}
But in the code you included it infers only as string
, for some reason ( maybe someone in the know can explain).
Once TypeScript fails to infer something you yourself know to be true, you can usually force the compiler to bend to your will by an annotation (in the case of bivariant parameters), or a type assertion.
In my case, I'd probably have done this instead:
type K = keyof ts.LanguageService
for (const k in oldLS) {
proxy[k as K] = function() {
return oldLS[k as K].apply(oldLS, arguments);
}
}
but that's a judgment call. 🤷
Hope that helps; good luck.
I guess RyanCavanaugh would be the best person to answer this if the snippet is taken from his sample-ts-plugin repo, but I'll take a stab at it anyway.
What does the casting on (<any>proxy)[k] accomplish since it is on the left side of the assignment?
It casts the variable proxy
to any
before the property k
is accessed.
This is to ignore compiler errors (I assume).
aren't all objects accessible via the bracket notation?
Not if noImplicitAny compiler option is on.
Try to toggle the noImplicitAny
option in this example.
(what is this code trying to accomplish)?
It's taking an existing function from the original info.languageService
and exposing it as a method of proxy
.
As noted in the comments, (<any>proxy)[k] = (<any>oldLS)[k];
might not work correctly because the original function would be called with a wrong this
context.
Bergi's shorter (<any>proxy)[k] = oldLS[k].bind(oldLS);
version would work in any project where programmer sanity is maintained, but it could "fail" to call the correct function if oldLs[k]
method was initialized lazily or changed later.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With