A user-defined type guard performs a runtime check to determine whether or not value of a particular type satisfies a type predicate.
If there is no relationship between the value's type and the type in the type predicate, the guard would make no sense. For example, TypeScript won't allow a user-defined guard like this:
function isString(value: Date): value is string {
return typeof value === "string";
}
and will effect this error:
[ts] A type predicate's type must be assignable to its parameter's type.
Type 'string' is not assignable to type 'Date'.
A Date
value will never be a string
, so the guard is pointless: its runtime check is unnecessary and should always return false
.
When you specify a generic, user-defined type guard, T
could be anything, so - as with Date
- for some types, the type guard would make no sense.
If you really don't want to use any
, you could use an empty interface - {}
- instead:
function isString(value: {}): value is string {
return typeof value === "string";
}
If you also want to allow for null
and undefined
values to be passed to the guard, you could use:
function isString(value: {} | null | undefined): value is string {
return typeof value === "string";
}
Regarding the error message, the predicate type must be assignable to the value type because the type guard is used to check whether a value with a less-specific type is in fact a value with a more-specific type. For example, consider this guard:
function isApe(value: Animal): value is Ape {
return /* ... */
}
Ape
is assignable to Animal
, but not vice versa.
(value: {}): value is string => { ... }
instead. As for the error, it's weird; it seems backwards.T
needing to be assignable tostring
would make more sense, to me. E.g TypeScript should know thatDate
will never be assignable tostring
, so such a predicate would make no sense. – Kuska(value: any) => value is string
as a type predicate is worse, right? I can pass it aDate
if I want. – FortyfiveT
is more like writing a whole bunch of functions. Try writing a user-defined type guard like(value: Date): value is string => { ... }
and you'll see what I mean. – Kuskaa -> Boolean
" so if any of those functions doesn't exist, then the generic doesn't exist. Nice! Could you write up an answer? – Fortyfive