Skip to content

Conditional types wrongly work with indexed access and object type (regression) #23800

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
falsandtru opened this issue May 1, 2018 · 3 comments
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@falsandtru
Copy link
Contributor

cc @ahejlsberg

TypeScript Version: 2.9.0-dev.20180501

Search Terms:

Code

type A<T, V> = { [P in keyof T]: T[P] extends V ? 1 : 0; };
type B<T, V> = { [P in keyof T]: T[P] extends V | object ? 1 : 0; };

type a = A<{ a: 0 | 1 }, 0>; // { a: 0; }
type b = B<{ a: 0 | 1 }, 0>; // { a: 1; }

Expected behavior:

type b = B<{ a: 0 | 1 }, 0>; // { a: 0; }

Actual behavior:

type b = B<{ a: 0 | 1 }, 0>; // { a: 1; }

Playground Link:

Related Issues:

@falsandtru falsandtru changed the title Indexed access breaks with object type (regression) Conditional types wrongly work with Indexed access and object type (regression) May 1, 2018
@falsandtru falsandtru changed the title Conditional types wrongly work with Indexed access and object type (regression) Conditional types wrongly work with indexed access and object type (regression) May 1, 2018
@mhegazy
Copy link
Contributor

mhegazy commented May 1, 2018

I see both as { a: 0 } on latest and on 2.8.3 (playground)

@mhegazy
Copy link
Contributor

mhegazy commented May 1, 2018

never mind.. looks like we broke it yesterday.

@mhegazy mhegazy added the Bug A bug in TypeScript label May 1, 2018
@mhegazy mhegazy added this to the TypeScript 2.9 milestone May 1, 2018
@ahejlsberg
Copy link
Member

ahejlsberg commented May 1, 2018

The immediate cause of this is #23768. However, it just exposes indexed access types to an issue that already exists with regular type parameters:

function foo<T, U>(x: T) {
    let a: object = x;  // Error as expected
    let b: U | object = x;  // No error!
}

The problem is caused by some logic in structuredTypeRelatedTo that specifically excludes checking the default {} constraint of an unconstrained type parameter against a target type of object. However, that logic doesn't kick in when the target is a union type that includes object.

Instead of attempting to exclude cases, when the source is an unconstrained type variable I think we need to check if the target is an empty object type or a union containing an empty object type.

@ahejlsberg ahejlsberg assigned ahejlsberg and unassigned weswigham May 1, 2018
@ahejlsberg ahejlsberg added the Fixed A PR has been merged for this issue label May 1, 2018
@microsoft microsoft locked and limited conversation to collaborators Jul 31, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

4 participants