Skip to content

ThisType doesn't work when extending it with an interface #46835

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
DetachHead opened this issue Nov 17, 2021 · 5 comments
Closed

ThisType doesn't work when extending it with an interface #46835

DetachHead opened this issue Nov 17, 2021 · 5 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@DetachHead
Copy link
Contributor

Bug Report

πŸ”Ž Search Terms

thistype interface

πŸ•— Version & Regression Information

4.6.0-dev.20211116

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

interface Foo {
    foo: () => void;
}

interface NewThisInterface extends ThisType<Foo> {
    hello: () => void
}

type NewThisType = ThisType<Foo> & {
    hello: () => void
}

const functions: NewThisType = {
    hello: function() {
        this.foo(); //works
    }
}

const functions2: NewThisInterface = {
    hello: function() {
        this.foo(); //doesn't work?
    }
}

πŸ™ Actual behavior

Property 'foo' does not exist on type 'NewThisInterface'.(2339)

πŸ™‚ Expected behavior

no error

@MartinJohns
Copy link
Contributor

Possibly because interface and type are not equivalent. Interfaces are subject to declaration merging, and don't extend Record<string, unknown>.

@DetachHead
Copy link
Contributor Author

DetachHead commented Nov 17, 2021

yeah i'm aware of the differences between types and interfaces, but i don't see how any of those differences would break ThisType, though it's hard to tell because ThisType seems to be intrinsic, although it isn't marked as such (#46836)

@fatcerberus
Copy link

fatcerberus commented Nov 17, 2021

The purpose of ThisType is to change the contextual type of anything assigned to it (e.g. object literals without an explicit this type on their methods). extends isn't assignment so inheriting from it doesn't work.

(Contextual typing being the same mechanism that infers parameter types of callbacks).

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Nov 18, 2021
@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Nov 18, 2021

extends and & are different operations. extends "copies down" the operand type's members, and ThisType is just a marker type, so effectively nothing happens because there is nothing to copy down. Intersection is intersection, so when contextually typing the function, we can successfully find the nominal ThisType among the intersection's constituents.

This wouldn't be fixable without doing some heavy-duty changing of what extends means in a way that would have observable follow-on effects, and this behavior has been present since 3.3.3 without anyone else noticing, so I'm going to round this up to "intended" behavior.

@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

5 participants