Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The is! operator is a negated type test relational operator that evaluates at runtime whether an object is not an instance of a specified type. It returns a boolean value: true if the object’s runtime type does not match or inherit from the target type, and false if it does. Semantically, expression is! Type is logically equivalent to !(expression is Type). Syntactically, however, they are different: is! is a distinct relational operator token in Dart’s grammar, whereas !(...) utilizes a unary logical NOT operator combined with grouping parentheses.

Syntax

expression is! Type
  • expression: Any valid Dart expression that evaluates to an object.
  • Type: The target Dart type (e.g., String, int, or a custom class) against which the expression’s runtime type is evaluated.

Type Promotion via Guard Clauses

A critical mechanic of the is! operator is its integration with Dart’s control flow analysis for type promotion. When is! is used in a guard clause (such as an if statement that exits the current scope via return or throw), the Dart compiler promotes the static type of the variable to the target type for the remainder of the current scope.
void processValue(Object value) {
  if (value is! String) {
    return; // Exits the scope if value is not a String
  }
  
  // Control flow analysis guarantees 'value' is a String here.
  // The static type is promoted from Object to String, allowing access to String methods.
  print(value.toUpperCase()); 
}

Evaluation Mechanics

The is! operator relies strictly on the runtime type of the object, ignoring the static compile-time type of the variable holding the reference.

1. Strict Type Negation

If the object in memory is not of the specified type, the operator yields true.
num value = 42; // Static type is num, runtime type is int

print(value is! String); // true
print(value is! double); // true
print(value is! int);    // false

2. Inheritance and Subtyping

The is! operator respects Dart’s object-oriented type hierarchy. If the expression evaluates to an object that is a subtype (child class) of the target Type, the is! operator will evaluate to false because the object is technically an instance of the parent type.
class Base {}
class Derived extends Base {}

Base instance = Derived();

print(instance is! Derived); // false (runtime type is Derived)
print(instance is! Base);    // false (Derived is a subtype of Base)
print(instance is! Object);  // false (all Dart objects inherit from Object)

3. Nullability Interactions

Under Dart’s sound null safety, the is! operator distinguishes between nullable (Type?) and non-nullable (Type) types when evaluating a null value. The null object is an instance of the Null class. In Dart’s type system, Never is the only true bottom type; however, the Null type acts as a subtype for all nullable types (as well as dynamic and void). It is not a subtype of non-nullable types.
int? nullableInt = null;

print(nullableInt is! int);  // true  (null is not a non-nullable int)
print(nullableInt is! int?); // false (null is a valid value for nullable int?)
print(nullableInt is! Null); // false (null is exactly of type Null)
Master Dart with Deep Grasping Methodology!Learn More