Skip to Content

Any

any holds any value; the cost is that the value’s type is unknown at compile time.

Storing Values and is Tests

var x: any = 42; print(x); x = "now some text"; print(x); print(x is string); x = 3.5; print(x is float);
42 now some text True True

is tests whether the value has type float and returns a bool. A value stored in any loses its concrete type information at compile time, and calling its methods directly is rejected by the compiler. For how to use a value once narrowed, see Patterns.

Warning

Member access on any is rejected outright at compile time; narrow with is first, then take the member. Treat any as a last resort.

Conversions with an any source (o is T, o as T, the checked conversion T(o)) all go through a runtime check; see Conversions.

The Shape of is Narrowing

v is T type-tests an any value; when the test passes, the narrowed value can be bound in a direct condition or an && chain:

func Describe(v: any) -> string { if v is int n { return $"int {n}"; } if v is string s { return $"string {s}"; } return "something else"; } print(Describe(42)); print(Describe("word")); print(Describe(2.5));
int 42 string word something else

Narrowing only works in direct conditions and && chains: the negated form !(v is T p) and the pure bool position (val b = v is T p;) are not allowed. For the latter, use the binding-free v is T.

Boxing Semantics

Scalars inside any are boxed: at runtime every value carries its real type, and the is test and narrowing judge by it, in the same family as generic erasure. A value that matches no branch falls through to the fallback string (2.5 above is neither int nor string).

typeof and Type Identity

print(typeof(int) == typeof(int), typeof(string) == typeof(int)); val v = 3.5; print(v is float); print(v is int);
True False True False

typeof(T) produces the Type value of a type, which can be compared and passed around. The is decision follows the compatibility between the value and the target type: 3.5 is a float, not an int.

A value’s real runtime type can be queried with Reflect.TypeOf; the mapping rules are covered in Reflection.

Heterogeneous Containers

list<any> holds heterogeneous values, and iterating with element-by-element is narrowing is the most common shape:

val bag = new list<any>(); bag.Add(1); bag.Add("word"); bag.Add([1, 2]); for item in bag { if item is int n { print("int", n); } elif item is string s { print("str", s); } else { print("other"); } }
int 1 str word other

The array literal [1, 2] is an int[], neither int nor string, so it lands in the fallback.

Costs and Limits

  • Member access is rejected at compile time: .field / .method() on any is never accepted; narrow with is first. any is not a universal container, so avoid overusing it.
  • Exempt from null-check narrowing: null checks involving any do not go through the nullable-narrowing state machine; any? must be checked on its own.
  • Once a container value is stored in any, generic instantiation tests such as is list<int> never match (the runtime does not distinguish by type arguments); do not rely on them for exact type checks.
Last updated on October 11, 2026