GithubHelp home page GithubHelp logo

Comments (4)

Andarist avatar Andarist commented on April 28, 2024

Here the source signature (<H extends Host2>(host: H): Page<H>) gets instantiated in context of the target signature ((...args: any[]): IPage<Host1>). That gets us a new source: (host: any): Page<any>. So the problem is that the any from the argument list in your target becomes an inference source for H on the source side and gets picked as the inferred type. This corrupts the comparison of those 2 signatures.

An interesting thing about this is that this code path uses different logic for inference from a signature than inferFromSignature. The latter uses the same inference priority for parameters and return types but collects covariant and contravariant candidates separately (and a covariant candidate is often preferred). This case uses different priorities (InferencePriority.ReturnType is weaker than InferencePriority.None) and collects everything as covariant candidates.

from typescript.

martaver avatar martaver commented on April 28, 2024

To paraphrase @Andarist, my understanding of why H is inferred as any is because:

  • H exists in two places, as a parameter and as a return type.
  • H corresponds to any in the parameter in the inference context of (...args: any[]) => IPage<Host1>.
  • H could also be Host1, but typeof Host2Page is invariant, and (IIUC) TS prefers the parameter type anyway, so any is inferred over Host1.

From this perspective, I think TS is acting as intended, and the problem is actually the misuse of (...args: any[]) which has colloquially come to mean "I don't care about the parameters", instead of what it actually means which is "Must accept any and all parameters".

The solution we found was to use a constructor type as the inference context that allows parameters and return types to be contravariant and covariant respectively, e.g.

type PageCtor<T extends IHost, TIn extends T = T, TOut extends T = T> = new (host: TIn) => IPage<TOut>

This allows TIn and TOut to be inferred independently of each other, which is usually why (...args: any[]) is used - to prevent the args from getting in the way of the return type.

Here it is in action: https://tsplay.dev/WGbO9m

I'm going to suggest that this issue is closed as 'working as intended', however @Andarist might have an opinion about whether everything is as it should be.

It's probably worth considering whether there could be a better way to express a constructor type that keeps its variance.

from typescript.

fatcerberus avatar fatcerberus commented on April 28, 2024

(...args: any[]) which has colloquially come to mean "I don't care about the parameters", instead of what it actually means which is "Must accept any and all parameters".

Yep, contravariance strikes again. Just like how (x: Animal) => void doesn't mean "the parameter is some kind of animal" but rather "must accept any kind of animal"

from typescript.

typescript-bot avatar typescript-bot commented on April 28, 2024

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

from typescript.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.