Skip to content

incorrect result with conditional type and boolean #41053

@unional

Description

@unional

TypeScript Version: 4.0.2

Search Terms:

"conditional type" "boolean" "incorrect result"

Code

type HasKey<T, K> = K extends keyof T ? true : false
type SimpleNot<X extends boolean> = X extends true ? false : true
type SimpleAnd<A, B> = A extends true ? B extends true ? true : false : false
type IsDisjointSimple<A, B> = SimpleAnd<SimpleNot<HasKey<A, keyof B>>, SimpleNot<HasKey<B, keyof A>>>

type If<Cond extends boolean, Then, Else> = Cond extends true ? Then : Else
type Equal<A, B> =
  (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2)
  ? true : false
type And<A extends boolean, B extends boolean> = If<
  Equal<A, true>,
  B,
  If<
    Equal<B, true>,
    A,
    If<
      Equal<A, boolean>,
      If<Equal<B, boolean>, boolean, false>,
      false
    >
  >
>
type Not<X extends boolean> = If<
  Equal<X, boolean>,
  boolean,
  If<Equal<X, true>, false, true>
>
type IsDisjoint<A, B> = And<Not<HasKey<A, keyof B>>, Not<HasKey<B, keyof A>>>

type Foo = { a: 1 }
type Boo = { b: 1 }

// false - correct
type fooHasBooKeys = HasKey<Foo, keyof Boo>

// true - correct
type fooNoBooKeysSimple = SimpleNot<HasKey<Foo, keyof Boo>> 

// true - correct
type isFooBooDisjointSimpleRaw = And<SimpleNot<HasKey<Foo, keyof Boo>>, SimpleNot<HasKey<Boo, keyof Foo>>> 

// true - correct
type isFooBooDisjointSimple = IsDisjointSimple<Foo, Boo>

// true - correct
type fooNoBooKeys = Not<HasKey<Foo, keyof Boo>>

// true - correct
type booNoFooKeys = Not<HasKey<Boo, keyof Foo>>

// true - correct
type isFooBooDisjointRaw = And<Not<HasKey<Foo, keyof Boo>>, Not<HasKey<Boo, keyof Foo>>> 

// false - wrong
// this should be identical to `isFooBooDisjointRaw`.
// The type is exactly the same.
type isFooBooDisjoint = IsDisjoint<Foo, Boo> 

The type utilities HasKey, If, Equal, And, Not are unit tested in unional/type-plus#71 and should be working as expected.

Playground Link:
playground

Related Issues:

Metadata

Metadata

Assignees

Labels

Needs InvestigationThis issue needs a team member to investigate its status.RescheduledThis issue was previously scheduled to an earlier milestone

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions