Skip to content

Different inference behavior between method and function syntax as opposed to arrow functions. #38623

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
dragomirtitian opened this issue May 17, 2020 · 1 comment · Fixed by #48538
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue
Milestone

Comments

@dragomirtitian
Copy link
Contributor

dragomirtitian commented May 17, 2020

TypeScript Version: 4.0.0-dev.20200516

Search Terms: object literal inference arrow function method

Expected behavior: M in inferred as { foo: () => void; }

Actual behavior:: When using function or method syntax M is inferred as unknown. Using arrow functions works fine.

Related Issues: #32230 But that specific case seems fixed

Code

function make<M>(o: { mutations: M,  action: (m: M) => void }) { }

make({
   mutations: {
       foo () { } // Nope
       // foo: function () { } // Nope 
       // foo: () => { } // OK
   },
   action: (a) => { a.foo() }
})
Output
"use strict";
function make(o) { }
make({
    mutations: {
        // foo () { } // Nope
        // foo: function () { } // Nope 
        foo: () => { } // OK
    },
    action: (a) => { a.foo(); }
});
Compiler Options
{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": 2,
    "target": "ES2017",
    "jsx": "React",
    "module": "ESNext"
  }
}

Playground Link: Provided

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Jun 8, 2020
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Jun 8, 2020
@HerringtonDarkholme
Copy link
Contributor

HerringtonDarkholme commented Aug 3, 2020

Personally I don't think this is a bug but rather an improvement.
A method signature will contextually type the object literal itself because this in method is the containing object literal. But an arrow function does not have this.

A user-side fix would be annotate this explicitly:

function make<M>(o: { mutations: M,  action: (m: M) => void }) { }

make({
   mutations: {
       foo(this: {}) { } // OK
   },
   action: (a) => { a.foo() }
})

However, we can skip the contextual typing if this isn't accessed in the method.

https://www.typescriptlang.org/play/?ts=4.0.0-dev.20200516#code/GYVwdgxgLglg9mABAWwIYGsCmAeAsgPgAo4AuRAbxRClVgQGczcAaRRVaeMMw5JgSkQBefIgBucGABNEAX0GVZAWABQqtFkLlVbKjTphGFHbt3A4cQlAAWMI+HRg4AdzAK5iAPSfEAeXQmcsyBHAY8qIIiFOwAdOaWgsoq8kA

HerringtonDarkholme added a commit to HerringtonDarkholme/vue-next that referenced this issue Aug 3, 2020
Due to the limitation of TS, prop validator must be fully annotated
refer to microsoft/TypeScript#38623
yyx990803 pushed a commit to vuejs/core that referenced this issue Aug 14, 2020
Due to the limitation of TS, prop validator must be fully annotated
refer to microsoft/TypeScript#38623
@typescript-bot typescript-bot added the Fix Available A PR has been opened for this issue label Apr 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue
Projects
None yet
4 participants