diff --git a/src/type/assert.spec.ts b/src/type/assert.spec.ts new file mode 100644 index 000000000..b57e0ca59 --- /dev/null +++ b/src/type/assert.spec.ts @@ -0,0 +1,23 @@ +import { Test, Type } from '..' + +type Assert_Spec = [ + /** + * Can cast a type to itself. + */ + Test.Expect, true>, + + /** + * Can cast a type to a subtype. + */ + Test.Expect, true>, + + /** + * Can cast a type to a supertype. + */ + Test.Expect, boolean>, + + /** + * Returns `never` if the types are not related. + */ + Test.Expect, never> +] diff --git a/src/type/assert.ts b/src/type/assert.ts new file mode 100644 index 000000000..b31823ad2 --- /dev/null +++ b/src/type/assert.ts @@ -0,0 +1,43 @@ +import { Kind } from '..' + +/** + * `_$assert` is a generic type that casts a type `T` to a type `U`, but only if `U` is a narrower or wider version of `T`. + * If an impossible coercion to an unrelated type is attempted, it returns `never`. + * + * This behavior is modeled after TypeScript's type assertion using the `as` operator. + * @see {@link Type._$cast} for a more permissive version of this type that only performs downcasts or coercions to unrelated types. + * + * @template T - The type to assert. + * @template U - The type to assert to. + * + * @example + * type T0 = _$assert // true + * type T1 = _$assert // true + * type T2 = _$assert // boolean + * type T3 = _$assert // never + */ +export type _$assert = [T] extends [U] ? U : [U] extends [T] ? U : never + +interface Assert_T extends Kind.Kind { + f(x: this[Kind._]): _$assert +} + +/** + * `Assert` is a type-level function that casts a type `T` to a type `U`, but only if `U` is a more or less specific version of `T`. + * If an impossible coercion to an unrelated type is attempted, it returns `never`. + * + * This behavior is modeled after TypeScript's type assertion using the `as` operator. + * @see {@link Type._$cast} for a more permissive version of this function that only performs downcasts or coercions to unrelated types. + * + * @template T - The type to assert. + * @template U - The type to assert to. + * + * @example + * type T0 = $<$, true> // true + * type T1 = $<$, true> // true + * type T2 = $<$, boolean> // boolean + * type T3 = $<$, 0> // never + */ +export interface Assert extends Kind.Kind { + f(x: this[Kind._]): Assert_T +} diff --git a/src/type/index.ts b/src/type/index.ts index 2754b2eb1..0d7ea72ff 100644 --- a/src/type/index.ts +++ b/src/type/index.ts @@ -1,3 +1,4 @@ +export * from './assert' export * from './cast' export * from './display' export * from './infer'