#Why doesn't tsc catch this error at compile time?

37 messages · Page 1 of 1 (latest)

tight wigeon
#

I have defined this function on the right to have a this

#

But the code on the upper left let's me call the function without having a this (of that type)

#

Why isn't this erroring at compile time?

#

Let me pose this a different way: would typescript normally complain about this?

pearl kindle
#

It looks like the issue is that the interface between the two places is getVsCodePath: () => string.

#

Which doesn't specify that a this type is required.

tight wigeon
#

Oh yeah!

#

Thank you. I don't think I would've thought of that without another pair of eyes

#

Thanks @pearl kindle

pearl kindle
#

And yeah, it looks like TS allows assigning this param functions to non-this param function types

short peakBOT
#
const func = function (this: string) { return "foo" }
func();
//^^^^
// The 'this' context of type 'void' is not assignable to method's 'this' of type 'string'.

const func2: () => string = func;
func2();
pearl kindle
#

Strictly speaking... it probably shouldn't but my guess is that this sort of checking broke too much code

tight wigeon
#

I see

#

With that fixed, what are my options for getting the upper left-hand corner to compile?

pearl kindle
#

Probably you shouldn't destructure the thing

tight wigeon
#

I know I can remove the deconstruction, but I'm wondering if there's a way to get the best of both worlds

#

To be honest, I'm surprised that javascript (or is it TS?) doesn't capture the this from the pre-deconstructed parameter

pearl kindle
#

It's JS

#

How this works in JS is that when you do x.y(z) it's basically y(/*this*/ x, z)

#

But if there's no . access then there's no this.

tight wigeon
#

yep! I understand that part. I guess I thought destructuring was syntactic sugar so it might give me some sugar in this case, too

pearl kindle
#

You can manually set it with .apply/.bind/.call but you'd still need a non-destructured object to set the this to

#

Or you can fix it on the 'right' side and not use this.

#
const item = {
   // other fields
   getVsCodePath: () => {
       return `${item.filePath}` //...
   }
}
tight wigeon
#

But if I do that, I would have to change the code to capture the-- yeah what you put

#

I like your solution better because it's less error-prone

pearl kindle
#

Yeah: probably that's my preference - it just avoids a footgun on the caller especially if the intent is to destructure

tight wigeon
#

In fact, I may have intended to do that and forgot. Maybe that's why it was missing from my type

#

oh dang it. No it wasn't my intent. The issue is that object doesn't have access to the filePath until later in the code. This lets me define the function and use a property before it exists

#

But I'm sure that the right move is to make it so that I can write the code the way you suggest

#

so I'll just fix that problem

#

Thanks again

#

!resolved

#

@pearl kindle Oh hey I have a follow-up question. Should I take this as a general rule: avoid this where possible?

pearl kindle
#

I think the advice I'd give is probably avoid this for anonymous objects like that.

#

For classes it's more expected that methods might rely on this and it's not a very normal thing to destructure a whole class object anyway