unnarrowed
v0.1.0
Published
A type-only TypeScript library for detecting unnarrowed types and asserting narrowing of generic types.
Downloads
6
Maintainers
Readme
narrowable
A type-only TypeScript library for detecting unnarrowed types and asserting narrowing of generic types.
What can I do with this?
- Associated types.
- Type narrowing assertions.
- Detecting when
infer T
uses theextends
type as a fallback.
Types
Unnarrowed
A type that has not been narrowed yet.
type Unnarrowed<T>
Usage:
interface AssociatedTypes {
DateType: Unnarrowed<Date | number | string>
}
NarrowedFrom
The narrowed form of an Unnarrowed
type.
If used on the right-hand side of an extends
statement such as
MyClass<U extends NarrowedFrom<T>>
where T
is Unnarrowed
, it will cause an
error when U = T
.
type NarrowedFrom<T>
Behavior:
- If
T
isUnnarrowed<U>
, returnsU
. - If
T
is an object withUnnarrowed<U>
properties, theUnnarrowed
is stripped from them. - Otherwise, returns an error type.
Usage:
type DateType = Unnarrowed<Date | number | string>
type DateGetter<T extends NarrowedFrom<DateType> = NarrowedFrom<DateType>> = () => T;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <-- assert narrowing
/** Defined elsewhere */
declare function getPublishDate(package: string): DateType;
/**
* Prints a date returned by a DateGetter.
*/
function printDateFrom<F extends DateGetter>(getter: F) {
console.log(getter());
}
printDateFrom(() => new Date()); // ok
printDateFrom(() => getPublishDate("unnarrowed"));
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <-- error, it returns unnarrowed DateType
AssertNarrowed
Asserts that the given type has been narrowed from an Unnarrowed<U>
.
type AssertNarrowed<T, Options = {}>
Options:
{
// If set to `true`, the assertion will only pass if the type is
// narrowed to a single, non-union type.
strict?: true | false
// If set, this type will be returned when the assertion fails.
failType: any;
}
Usage:
type GlasswareMaterial = Unnarrowed<'glass' | 'crystal'>;
interface Glassware<T extends GlasswareMaterial> {
type: AssertNarrowed<T, {
strict: true,
failType: never,
}>
}
const aWineGlass: Glassware<'glass' | 'crystal'> = {
type: "glass"
// ~~~~ <-- T is not strictly narrowed, so `type` is never
}
AssertStrictlyNarrowed
An alias for AssertNarrowed
with the strict
option set to true
.
type AssertStrictlyNarrowed<T, Options = {}>
Utility Types
IsUnnarrowed
Checks if a type is Unarrowed<T>
.
If the given type is any
, an error type will be returned.
type IsUnnarrowed<T, WhenTrue=true, WhenFalse=false, WhenError=/* error */>
Usage:
type should_be_true = IsUnnarrowed<Unnarrowed<string>>;
type should_be_false = IsUnnarrowed<string>;
type is_error = IsUnnarrowed<any>;
IsNarrowed
Checks if a type is not Unarrowed<T>
.
If the given type is any
, the WhenTrue
type will be returned.
type IsUnnarrowed<T, WhenTrue=true, WhenFalse=false, WhenError=WhenTrue>
Usage:
type should_be_true = IsNarrowed<string>;
type should_be_false = IsNarrowed<Unnarrowed<string>>;
type also_true = IsNarrowed<any>;
IsStrictlyNarrowed
Checks if a type is not Unarrowed<T>
, and is not a type union.
If the given type is any
, the WhenFalse
type will be returned.
type IsUnnarrowed<T, WhenTrue=true, WhenFalse=false, WhenError=WhenTrue>
Usage:
type should_be_true = IsStrictlyNarrowed<string>;
type should_be_false = IsStrictlyNarrowed<Unnarrowed<string>>;
type also_false_1 = IsStrictlyNarrowed<string | boolean>;
type also_false_2 = IsStrictlyNarrowed<any>;