Skip to content

any appears to shortcircut structural type checking #31295

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

Open
webstrand opened this issue May 7, 2019 · 2 comments
Open

any appears to shortcircut structural type checking #31295

webstrand opened this issue May 7, 2019 · 2 comments
Labels
Bug A bug in TypeScript Domain: Conditional Types The issue relates to conditional types Domain: Variance Relationships The issue relates to variance relationships between types
Milestone

Comments

@webstrand
Copy link
Contributor

TypeScript Version: 3.5.0-dev.20190507

Search Terms:
any, unsound, extends, never

Code

// I detect if F is `any` by checking if F extends `never`.
// (F extends never ? true : false) produces `true|false` for `F = any`
// and `false` or `never` for everything else.
type Decider<F> = {
	prop: (F extends never ? true : false) extends false ? "isNotAny" : "isAny";
};

let foo!: Decider<string>;
let bar: Decider<any> = foo;

let fooProp: "isNotAny" = foo.prop;
let barProp: "isAny" = bar.prop;

Expected behavior:
Either bar.prop should have the type "isAny"|"isNotAny" or foo should not be assignable to bar.

Actual behavior:
foo is assignable to bar and bar.prop has the type "isAny" which is incompatible with foo.prop's "isNotAny".

Playground Link: link

@jack-williams
Copy link
Collaborator

jack-williams commented May 7, 2019

This is an issue with variance markers and conditional types I think. The issue is that when assigning foo to bar the checker is just relating the type arguments (string and any) which are related. The markers are missing the fact that the type arguments appear as check types in a conditional type.

cc @weswigham

Related: #31251

@jcalz
Copy link
Contributor

jcalz commented May 7, 2019

This is not directly relevant to the issue but in case you want to be able to distinguish any from never you can use the following instead:

type IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N;
type Decider<F> = {
	prop: IfAny<F, "isAny", "isNotAny">
};

Which, again, doesn't address the actual assignability problem you're talking about.

@weswigham weswigham added Bug A bug in TypeScript Domain: Conditional Types The issue relates to conditional types Domain: Variance Relationships The issue relates to variance relationships between types labels May 8, 2019
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.6.0 milestone Jun 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Domain: Conditional Types The issue relates to conditional types Domain: Variance Relationships The issue relates to variance relationships between types
Projects
None yet
Development

No branches or pull requests

6 participants