Last active
August 12, 2024 22:46
-
-
Save zachhardesty7/1b5b6f6de328f1bb7c78cbe96ba5c720 to your computer and use it in GitHub Desktop.
TS `Expect` type testing helper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// copyright 2024 Zach Hardesty | |
// want to check this out in the TypeScript playground? | |
// visit the following link to automatically see the latest version! | |
// https://www.typescriptlang.org/play?jsx=0#gist/1b5b6f6de328f1bb7c78cbe96ba5c720 | |
/** | |
* Passes thru successful test input, errors with inputs that are not equal. nice when | |
* you have a bunch of `never`s. can handle checking if things are `any` or `unknown` too. | |
* | |
* Can be used in the middle of an expression and composed to check each step | |
* | |
* **NOTE:** when both or neither of input/expected are `any`, checks they extend each | |
* other, otherwise only 1 is `any` and this manually shows an error message (instead of | |
* `never` for readability) since `any` is a supertype of everything and input would | |
* always match expected | |
* | |
* @example | |
* // no errors here, `TypeTest1` silently becomes `never` | |
* type TypeTest1 = false extends true ? { a: string } : never | |
* // TS shows an error here and `TypeTest2` still becomes `never` | |
* type TypeTest2 = Expect< | |
* false extends true ? { a: string } : never, | |
* { a: string } | |
* > | |
* // passing test, but `TypeTest3` also becomes the result of simplifying the input ({ a: string }) | |
* type TypeTest3 = Expect<true extends true ? { a: string } : never, { a: string }> | |
* | |
* @todo Check for perf issues with recursion | |
* @see https://github.com/sindresorhus/type-fest/blob/main/source/is-any.d.ts | |
*/ | |
type Expect< | |
TInput extends TCheck, | |
TExpected extends TCheck, | |
TCheck = IsAny<TInput> extends IsAny<TExpected> | |
? TInput extends TExpected | |
? TInput | |
: TExpected | |
: "exactly `any` type", | |
> = TInput; | |
/** @see https://github.com/sindresorhus/type-fest/blob/main/source/is-any.d.ts */ | |
type IsAny<T> = 0 extends 1 & NoInfer<T> ? true : false; | |
/** incorrectly allows any type when checking for exactly `any` */ | |
type BasicExpect< | |
TInput extends TIntersect, | |
TExpected extends TIntersect, | |
TIntersect = TExpected & TInput, | |
> = TInput; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment