Skip to content

Wrong type parameter inference when there is mapped types and Readonly in the argument type #33164

Closed
@ktsn

Description

@ktsn

TypeScript Version: 3.6.1-rc, 3.6.2

Search Terms:
mapped types, argument, overload, readonly, intersection

Code

interface Instance {
  _instanceBrand: never
}

type DataDef<Data, Props> = (this: Readonly<Props> & Instance) => Data

type PropsDefinition<T> = {
  [K in keyof T]: T[K]
}

interface Options<
  Data = object | ((this: Instance) => object),
  PropsDef = PropsDefinition<Record<string, any>>
> {
  data?: Data
  props?: PropsDef
  watch?: Record<string, WatchHandler<any>>
}

type WatchHandler<T> = (val: T, oldVal: T) => void;

type ThisTypedOptions<Data, Props> =
  object &
  Options<DataDef<Data, Props>, PropsDefinition<Props>> &
  ThisType<Data & Readonly<Props> & Instance>

declare function test<Data, Props>(fn: ThisTypedOptions<Data, Props>): void;
declare function test(fn: Options): void;

test({
  props: {
    foo: ''
  },

  data(): { bar: boolean } {
    return {
      bar: true
    }
  },

  watch: {
    foo(newVal: string, oldVal: string): void {
      this.bar = false
    }
  }
})

Expected behavior:
No errors. test should choose the first overload.

Actual behavior:
There is an error because the test choose the fallback overload and this is not typed as expected.

Type 'false' is not assignable to type 'WatchHandler<any>'.

If you change the fallback overload's argument type to never, you can see that it wrongly infers Props type parameter in error message.

This will not happen if you do either following things:

  • Replace all appearance of PropsDefinition<XXX> with just XXX (PropsDefinition is just returning the same type but using mapped type)
  • Replace the this type of DataDef (Readonly<Props> & Instance) with Props & Instance

Playground Link:
http://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgJIgM5jiJyDeAUMsgPqhY5IBCUOAJgFzIgQBu0hAvoYWAJ4AHFABE42ERBgAeMdgA0yAApQA9oIwA+ZAF5kACjAALYBmYAlCHHqqQAG37SV6rcgBkaTNlwQAlLu05OF4BYWU1DUkYUGAwYFtpABVtPSISAG0AaWRQZABrCH5VGGREgF1mRKyy7l5QSFhEFAB5QTjbDGliZCDdZFUAIwArCAQwZAAfA0MTM09KH38dbUGRsd95budIqT7tjCiY9pBpSwRVKHppLChQAHNFHH5NTUJtNOR6cTgAfmYg7qCCIYP7hFxRboAd3ECCMoLOFyuN3uigA6jCjAAJBh2aDSJ4vWp8IQodFgWHYkD0XFQJIpAxsOB2SqKVR2egANSZlSW2jYqmA9AA3CESaVZokSfRWsdOkFFPsUt1VqNxm5ujL4phZN8ojqFGCNJoFcDDiBYlqnMCXu5uokJST9XB3MhLNZbA4rS5tB50AskK9CPRRnY4FAUDAAK64Y7ISBYJ0m736GAgSoO4TStpauXfJNG3zMfmCkXBhCh8PIKMxrVxiBYFNp5CajqF5DF4UhetgfQfIEuZgfEgwVSqZgAcnH3S4m26X2w+jb+GQAzDzAGo9xOGQXAI3RI4bAkagID3JHPK7XcagkYg+5309nJGh5KMg-vI9U+lYkK5zOQyIgA8-Tsn+zCAXcbYdmeF5xrMAB0q5QH08B2Bgd4XjwJA8FwvhAA
(There is no error on playground as the Ts version is 3.5)

Related Issues:
This is originally reported on Vue.js repo.
vuejs/vue#10455

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptDomain: Type InferenceRelated to type inference performed during signature resolution or `infer` type resolution

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions