Skip to content

wrong type infer in 3.6.0-dev.20190725 #32572

Closed
@bluelovers

Description

@bluelovers

TypeScript Version: 3.4.0-dev.201xxxxx

Search Terms:

Code

this code work at 3.5.2 and 3.6.0-dev.20190704

but fail at 3.6.0-dev.20190725

import Bluebird = require('bluebird');

let a: string[] = [];

Bluebird.resolve(a as string[])
	.mapSeries(async function (vvvv)
	{
		console.log(vvvv.toUpperCase())

		return vvvv;
	})
;

Bluebird.resolve(a as string[])
	.mapSeries(function (vvvv)
	{
		console.log(vvvv.toUpperCase())

		return vvvv;
	})
;

Bluebird.resolve(a as string[])
	.mapSeries((vvvv) =>
	{
		console.log(vvvv.toUpperCase())

		return vvvv;
	})
;

Expected behavior:

no error and infer to string

Actual behavior:

vvvv infer to unknown

image

Playground Link:

Related Issues:

Activity

jcalz

jcalz commented on Jul 26, 2019

@jcalz
Contributor

Ideally bug reports will have a completely self-contained example that you don't need external libraries to reproduce. Like maybe this:

interface Prom<T> {
  mapSeries<Q>(
    this: Prom<T & Iterable<Q>>,
    iterator: (item: Q) => any
  ): any;
}

declare const p: Prom<string[]>;

p.mapSeries(async function (s) {
  console.log(s.toUpperCase()); // error, s is unknown 3.6.0-dev.20190725
});

Playground (but there's no error in v3.5.1)

Something about this and not being able to infer Q from the type T & Iterable<Q> in this scenario. (Workaround: replace Q with or constrain Q to (T extends Iterable<infer I> ? I : never))

Not sure if this is really a bug or what. Seems like it might be a breaking change for Bluebird, though.

Caused by #32386/#32460? (🃏wild guess❓)

ahejlsberg

ahejlsberg commented on Jul 26, 2019

@ahejlsberg
Member

This is caused by #32460. Consider the following simplified example:

declare function foo1<T>(obj: string[] & Iterable<T>): T;
declare function foo2<T>(obj: string[] & T): T;

declare let sa: string[];
declare let sx: string[] & { extra: number };

let x1 = foo1(sa);
let y1 = foo1(sx);

let x2 = foo2(sa);
let y2 = foo2(sx);

With 3.5.x we produced the following results:

let x1 = foo1(sa);  // string
let y1 = foo1(sx);  // unknown

let x2 = foo2(sa);  // string[]
let y2 = foo2(sx);  // { extra: number }

It's pretty clear that x1 and y2 are inconsistent, and unknown would be a better inference for x2.

With 3.6.0-dev.20190725 we produce:

let x1 = foo1(sa);  // unknown
let y1 = foo1(sx);  // unknown

let x2 = foo2(sa);  // unknown
let y2 = foo2(sx);  // { extra: number }

This has the better inference for x2 and it makes x1 and y1 consistent, but unknown is really not a good inference here. I think the desired outcome is:

let x1 = foo1(sa);  // string
let y1 = foo1(sx);  // string

let x2 = foo2(sa);  // unknown
let y2 = foo2(sx);  // { extra: number }

I have updated #32558 to implement this and I'm currently checking for effects on the DT tests.

self-assigned this
on Jul 26, 2019
added this to the TypeScript 3.6.1 milestone on Jul 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

    Development

    Participants

    @jcalz@bluelovers@ahejlsberg

    Issue actions

      wrong type infer in 3.6.0-dev.20190725 · Issue #32572 · microsoft/TypeScript