Typescript: Issue with type inference

Created on 26 Feb 2019  路  3Comments  路  Source: microsoft/TypeScript

The following demo shows an issue with TypeScript's type inference (tested with [email protected] and [email protected]).
I do not know whether this should really be considered a bug but at least the same is working fine with Flow.
Pardon me, in case this has already been issued somewhere else in the past.

The following is working properly with Flow => types of store and self are properly inferred as { count: number, increment(): void }.
Check here to see that the Flow code is fine.

// @flow

function createStore<T>(init: (self: T) => T): T {
  const ret: T = (({}: any): T)
  // assume some change detector logic here
  // (skipped to keep demo simple)
  Object.assign(ret, init(ret))
  return ret
}

const store = createStore(self => {
  return {
     count: 0,

     increment() {
       self.count++
     }
  }
})

console.log(store.count) // prints out 0
store.increment()
console.log(store.count) // prints out 1

Unfortunatelly the same is NOT working with TypeScript => types of store and self are inferred to {} instead of { count: number, increment(): void }.
TypeScript live demo: https://stackblitz.com/edit/typescript-sjuimf

function createStore<T>(init: (self: T) => T): T {
  const ret: T = {} as T
  // assume some change detector logic here
  // (skipped to keep demo simple)
  Object.assign(ret, init(ret))
  return ret
}

const store = createStore(self => {
  return {
     count: 0,

     increment() {
       self.count++ // <------ type error!!!
     }
  }
}) // return type is {} instead of { count: number, increment(): void }

// Type errors in each of the following three lines!!!
console.log(store.count) // prints out 0
store.increment()
console.log(store.count) // prints out 1
Design Limitation

Most helpful comment

@RyanCavanaugh Everything has its limitations - so if this is an already known minor limitation of TypeScript and there are no plans to enhance this in near future, then that's okay for me, of course. In that case, feel free to close this issue (in my particular use case I have already implemented an alternative that works fine with TypeScript's type inference as-is).

All 3 comments

FYI: The following modification works fine in TypeScript
TS live demo: https://stackblitz.com/edit/typescript-xyfjcg

function createStore<T>(init: () => T): T {
  const ret: T = {} as T
  // assume some change detector logic here
  // (skipped to keep demo simple)
  Object.assign(ret, init())
  return ret
}

const store = createStore(() => {
  return {
     count: 0,

     increment() {
       store.count++
     }
  }
})

console.log(store.count) // prints out 0
store.increment()
console.log(store.count) // prints out 1})

TypeScript's inference algorithm is not as good at dealing with argument-return value circularity.

@RyanCavanaugh Everything has its limitations - so if this is an already known minor limitation of TypeScript and there are no plans to enhance this in near future, then that's okay for me, of course. In that case, feel free to close this issue (in my particular use case I have already implemented an alternative that works fine with TypeScript's type inference as-is).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DanielRosenwasser picture DanielRosenwasser  路  3Comments

remojansen picture remojansen  路  3Comments

siddjain picture siddjain  路  3Comments

jbondc picture jbondc  路  3Comments

wmaurer picture wmaurer  路  3Comments