2023-05-03 11:06:20 +02:00
== Why is this an issue?
2023-07-27 16:07:07 +02:00
A type guard is a TypeScript feature that allows you to narrow the type of a variable within a conditional block of code. It is a way to tell the TypeScript compiler that an expression is of a certain type, based on some condition that you check at runtime.
2021-04-28 16:49:39 +02:00
2023-07-27 16:07:07 +02:00
[source,javascript]
----
function printLength(x: any) {
if (typeof x === 'string') {
console.log(x.length);
}
}
----
Type predicates are user-defined functions that work as type guards, where you define yourself how to narrow the type of an expression based on some custom condition. These are just functions with a return type of ``++argumentName is SomeType++``. Such functions return ``++true++`` if the argument is of the specified type.
[source,javascript]
----
function isString(x: any): x is string {
return typeof x === 'string';
}
2021-04-28 16:49:39 +02:00
2023-07-27 16:07:07 +02:00
function printLength(x: any) {
if (isString(x)) {
console.log(x.length);
}
}
----
2021-04-28 16:49:39 +02:00
2023-07-27 16:07:07 +02:00
One of the advantages of using such a function is that in a conditional block where the condition is a type guard, the compiler automatically performs the appropriate casts, so explicit casting becomes unnecessary.
2021-04-28 16:49:39 +02:00
2023-07-27 16:07:07 +02:00
Type predicates provide a more precise, readable, and flexible way to check types in your code, which can lead to more robust and maintainable code.
2021-04-28 18:08:03 +02:00
2023-07-27 16:07:07 +02:00
This rule raises an issue when a boolean function checking for the type of its only argument can be replaced with a type predicate.
2021-04-28 16:49:39 +02:00
2023-07-27 16:07:07 +02:00
[source,javascript,diff-id=1,diff-type=noncompliant]
2021-04-28 16:49:39 +02:00
----
2023-07-27 16:07:07 +02:00
function isSomething(x: BaseType): boolean { // Noncompliant
2021-04-28 16:49:39 +02:00
return (<Something>x).foo !== undefined;
}
if (isSomething(v)) {
(<Something>v).foo();
2023-07-27 16:07:07 +02:00
(v as Something).foo();
2021-04-28 16:49:39 +02:00
}
----
2023-07-27 16:07:07 +02:00
Transform the function into a type predicate, adding a return type annotation that specifies the type predicate.
2021-04-28 18:08:03 +02:00
2023-07-27 16:07:07 +02:00
[source,javascript,diff-id=1,diff-type=compliant]
2021-04-28 16:49:39 +02:00
----
2023-07-27 16:07:07 +02:00
function isSomething(x: BaseType): x is Something {
2021-04-28 16:49:39 +02:00
return (<Something>x).foo !== undefined;
}
if (isSomething(v)) {
v.foo();
}
----
2021-04-28 18:08:03 +02:00
2023-05-03 11:06:20 +02:00
== Resources
2021-04-28 16:49:39 +02:00
2023-07-27 16:07:07 +02:00
=== Documentation
2021-04-28 18:08:03 +02:00
2023-07-27 16:07:07 +02:00
* https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates[TypeScript - Using type predicates]
2021-06-02 20:44:38 +02:00
2021-06-03 09:05:38 +02:00
ifdef::env-github,rspecator-view[]
2021-09-20 15:38:42 +02:00
'''
== Implementation Specification
(visible only on this page)
2023-05-25 14:18:12 +02:00
=== Message
Change this boolean return type into a type predicate
=== Highlighting
The function declaration
2021-09-20 15:38:42 +02:00
2021-06-08 15:52:13 +02:00
'''
2021-06-02 20:44:38 +02:00
== Comments And Links
(visible only on this page)
2023-05-25 14:18:12 +02:00
=== on 14 Nov 2017, 21:23:12 Ann Campbell wrote:
\[~jeanchristophe.collet] from this description I don't understand what type guards do, and from the examples, I have no idea how they work.
2021-06-03 09:05:38 +02:00
endif::env-github,rspecator-view[]