Skip to content

Commit

Permalink
Correctly match boolean literal values (#899)
Browse files Browse the repository at this point in the history
`boolean` is effectively the union type `true | false` but the current
`isMatch` implementation will treat overlapping union types as matching.

This patch introduces a more strict type equivalence check based on
microsoft/TypeScript#27024 (comment)
and uses it when checking types that extend `boolean` for equivalence to
`boolean`.

The test added in this patch fails without the corresponding code changes
here.

Fixes #754.
  • Loading branch information
FukudaYoshiro committed Oct 11, 2021
1 parent 00e4c16 commit 2db1931
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 2 deletions.
15 changes: 13 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,22 @@ export type EnumSchema<T extends string | number | undefined> = {
}

/**
* Check if a type is an exact match.
* Check if a type is a match for another whilst treating overlapping
* unions as a match.
*/

export type IsMatch<T, G> = T extends G ? (G extends T ? T : never) : never

/**
* Check if a type is an exact match.
*/

export type IsExactMatch<T, U> = (<G>() => G extends T ? 1 : 2) extends <
G
>() => G extends U ? 1 : 2
? T
: never

/**
* Check if a type is a record type.
*/
Expand Down Expand Up @@ -322,7 +333,7 @@ export type StructSchema<T> = [T] extends [string | undefined]
? EnumSchema<T>
: T
: [T] extends [boolean]
? [T] extends [IsMatch<T, boolean>]
? [T] extends [IsExactMatch<T, boolean>]
? null
: T
: T extends
Expand Down
4 changes: 4 additions & 0 deletions test/typings/describe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ test<Describe<string & number>>((x) => {
return intersection([string(), number()])
})

test<Describe<false>>((x) => {
return literal(false)
})

test<Describe<42>>((x) => {
return literal(42)
})
Expand Down

0 comments on commit 2db1931

Please sign in to comment.