Skip to content
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

false equality with exactOptionalPropertyTypes #128

Open
tao-cumplido opened this issue Oct 30, 2024 · 5 comments
Open

false equality with exactOptionalPropertyTypes #128

tao-cumplido opened this issue Oct 30, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@tao-cumplido
Copy link

Not sure if this solvable, but .toEqualTypeOf() doesn't work correctly with the exactOptionalPropertyTypes config option.

import { expectTypeOf } from "expect-type";

type A = {
	a?: number | undefined;
}

type B = {
	b?: number;
}

declare const a: A;
declare const b: B;

expectTypeOf(a).toEqualTypeOf<{ a?: number }>(); // should fail
expectTypeOf(b).toEqualTypeOf<{ b?: number | undefined }>(); // should fail

expectTypeOf<{ a?: number }>(a); // errors as expected

The last line results in the following error message:

Argument of type 'A' is not assignable to parameter of type '{ a?: number; }' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
  Types of property 'a' are incompatible.
    Type 'number | undefined' is not assignable to type 'number'.
      Type 'undefined' is not assignable to type 'number'.(2379)

Playground

@mmkal
Copy link
Owner

mmkal commented Oct 30, 2024

Thanks - yeah, I haven't actually used this config so not sure if it's solvable either. If you've seen any ts tricks around that can detect the difference, I'd be open to a (non-breaking) update here.

@mrazauskas
Copy link
Contributor

mrazauskas commented Oct 30, 2024

By the way, TypeScript's internal programmatic API also confirms that these types are identical. With or without exactOptionalPropertyTypes: true set.

In a way, I would say that’s correct. These types are identical. (But not assignable, if exactOptionalPropertyTypes: true is set.)

I say so after thinking, if taking exactOptionalPropertyTypes: true into account matters while testing if types are identical? I would say that it does not. It even seems better to ignore it, because this option controls assignability check, but does not alter the type somehow.

(And assignability is another story. But again: does it matter to check whether TypeScript works correctly? That’s like testing a constant. Obviously with exactOptionalPropertyTypes: true types will not be assignable.)

Just thinking out loud. Might be this is simplified example and I have missed some detail.

EDIT. On second thought, I see how assignably checks could make sense.

@tao-cumplido
Copy link
Author

I'm not too familiar with the Compiler API but isn't it weird though, for types to be considered equal but not be assignable?

@mrazauskas
Copy link
Contributor

In a way it sounds strange. I was digging through internal TypeScript's logic, looking at AST and type objects. Hm.. Not sure I still agree with my yesterday’s thoughts ;D

A fix could be: after checking identically, compare assignability as well. Don’t know how to translate that into generic types. Programmatically that’s simple: tstyche/tstyche#357

By the way, tsds logic is somewhat similar. Although this approach has bugs: tsdjs/tsd#141.

@aryaemami59
Copy link
Collaborator

I'm a little late to the party, I'm going to see if there is a simple solution to this.

@aryaemami59 aryaemami59 added the bug Something isn't working label Nov 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants