Replace Type::(Is|As)Vector with Castable

Change-Id: Ic838aa783a279d0939a972773206fee2e33c4bff
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/34274
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/ast/type/access_control_type_test.cc b/src/ast/type/access_control_type_test.cc
index e02ee23..9a9bacc 100644
--- a/src/ast/type/access_control_type_test.cc
+++ b/src/ast/type/access_control_type_test.cc
@@ -32,6 +32,7 @@
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/texture_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -64,7 +65,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_FALSE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(AccessControlTypeTest, AccessRead) {
diff --git a/src/ast/type/alias_type_test.cc b/src/ast/type/alias_type_test.cc
index 46259a0..2a2d35b 100644
--- a/src/ast/type/alias_type_test.cc
+++ b/src/ast/type/alias_type_test.cc
@@ -33,6 +33,7 @@
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/texture_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -65,7 +66,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_FALSE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(AliasTypeTest, TypeName) {
diff --git a/src/ast/type/array_type_test.cc b/src/ast/type/array_type_test.cc
index b8119e8..7a3d351 100644
--- a/src/ast/type/array_type_test.cc
+++ b/src/ast/type/array_type_test.cc
@@ -28,6 +28,7 @@
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/texture_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -71,7 +72,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_FALSE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(ArrayTypeTest, TypeName) {
diff --git a/src/ast/type/bool_type_test.cc b/src/ast/type/bool_type_test.cc
index 4d8fa7e..52e64a7 100644
--- a/src/ast/type/bool_type_test.cc
+++ b/src/ast/type/bool_type_test.cc
@@ -24,6 +24,7 @@
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/texture_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -47,7 +48,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_FALSE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(BoolTypeTest, TypeName) {
diff --git a/src/ast/type/depth_texture_type_test.cc b/src/ast/type/depth_texture_type_test.cc
index 53200ae..51c7014 100644
--- a/src/ast/type/depth_texture_type_test.cc
+++ b/src/ast/type/depth_texture_type_test.cc
@@ -25,6 +25,7 @@
 #include "src/ast/type/pointer_type.h"
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -48,7 +49,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_TRUE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(DepthTextureTypeTest, IsTextureType) {
diff --git a/src/ast/type/f32_type_test.cc b/src/ast/type/f32_type_test.cc
index bd34468..8d356ee 100644
--- a/src/ast/type/f32_type_test.cc
+++ b/src/ast/type/f32_type_test.cc
@@ -24,6 +24,7 @@
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/texture_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -47,7 +48,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_FALSE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(F32TypeTest, TypeName) {
diff --git a/src/ast/type/i32_type_test.cc b/src/ast/type/i32_type_test.cc
index 093ed6a..fc9c75a 100644
--- a/src/ast/type/i32_type_test.cc
+++ b/src/ast/type/i32_type_test.cc
@@ -24,6 +24,7 @@
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/texture_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -47,7 +48,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_FALSE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(I32TypeTest, TypeName) {
diff --git a/src/ast/type/matrix_type_test.cc b/src/ast/type/matrix_type_test.cc
index 6335674..514d61d 100644
--- a/src/ast/type/matrix_type_test.cc
+++ b/src/ast/type/matrix_type_test.cc
@@ -24,6 +24,7 @@
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/texture_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -56,7 +57,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_FALSE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(MatrixTypeTest, TypeName) {
diff --git a/src/ast/type/multisampled_texture_type_test.cc b/src/ast/type/multisampled_texture_type_test.cc
index e08440d..32756ce 100644
--- a/src/ast/type/multisampled_texture_type_test.cc
+++ b/src/ast/type/multisampled_texture_type_test.cc
@@ -24,6 +24,7 @@
 #include "src/ast/type/pointer_type.h"
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -48,7 +49,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_TRUE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(MultisampledTextureTypeTest, IsTextureType) {
diff --git a/src/ast/type/pointer_type_test.cc b/src/ast/type/pointer_type_test.cc
index 6af8570..f50a6a7 100644
--- a/src/ast/type/pointer_type_test.cc
+++ b/src/ast/type/pointer_type_test.cc
@@ -24,6 +24,7 @@
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/texture_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -55,7 +56,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_FALSE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(PointerTypeTest, TypeName) {
diff --git a/src/ast/type/sampled_texture_type_test.cc b/src/ast/type/sampled_texture_type_test.cc
index 6c37a81..9e68b82 100644
--- a/src/ast/type/sampled_texture_type_test.cc
+++ b/src/ast/type/sampled_texture_type_test.cc
@@ -24,6 +24,7 @@
 #include "src/ast/type/pointer_type.h"
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -48,7 +49,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_TRUE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(SampledTextureTypeTest, IsTextureType) {
diff --git a/src/ast/type/sampler_type_test.cc b/src/ast/type/sampler_type_test.cc
index 9fd5ada..2353c8a 100644
--- a/src/ast/type/sampler_type_test.cc
+++ b/src/ast/type/sampler_type_test.cc
@@ -25,6 +25,7 @@
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/texture_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -59,7 +60,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_FALSE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(SamplerTypeTest, TypeName_Sampler) {
diff --git a/src/ast/type/storage_texture_type_test.cc b/src/ast/type/storage_texture_type_test.cc
index 961b1cb..4d71c41 100644
--- a/src/ast/type/storage_texture_type_test.cc
+++ b/src/ast/type/storage_texture_type_test.cc
@@ -27,6 +27,7 @@
 #include "src/ast/type/pointer_type.h"
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/u32_type.h"
+#include "src/ast/type/vector_type.h"
 #include "src/type_determiner.h"
 
 namespace tint {
@@ -52,7 +53,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_TRUE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(StorageTextureTypeTest, IsTextureType) {
diff --git a/src/ast/type/struct_type_test.cc b/src/ast/type/struct_type_test.cc
index 82227b1..d0ba1e8 100644
--- a/src/ast/type/struct_type_test.cc
+++ b/src/ast/type/struct_type_test.cc
@@ -62,7 +62,7 @@
   EXPECT_TRUE(ty->Is<StructType>());
   EXPECT_FALSE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(StructTypeTest, TypeName) {
diff --git a/src/ast/type/type.cc b/src/ast/type/type.cc
index 5204986..fdbc0e1 100644
--- a/src/ast/type/type.cc
+++ b/src/ast/type/type.cc
@@ -66,10 +66,6 @@
   return UnwrapIfNeeded()->UnwrapPtrIfNeeded()->UnwrapIfNeeded();
 }
 
-bool Type::IsVector() const {
-  return false;
-}
-
 bool Type::IsVoid() const {
   return false;
 }
@@ -95,7 +91,7 @@
 }
 
 bool Type::is_float_vector() {
-  return IsVector() && AsVector()->type()->is_float_scalar();
+  return Is<VectorType>() && As<VectorType>()->type()->is_float_scalar();
 }
 
 bool Type::is_float_scalar_or_vector() {
@@ -107,40 +103,32 @@
 }
 
 bool Type::is_unsigned_integer_vector() {
-  return IsVector() && AsVector()->type()->Is<U32Type>();
+  return Is<VectorType>() && As<VectorType>()->type()->Is<U32Type>();
 }
 
 bool Type::is_signed_integer_vector() {
-  return IsVector() && AsVector()->type()->Is<I32Type>();
+  return Is<VectorType>() && As<VectorType>()->type()->Is<I32Type>();
 }
 
 bool Type::is_unsigned_scalar_or_vector() {
-  return Is<U32Type>() || (IsVector() && AsVector()->type()->Is<U32Type>());
+  return Is<U32Type>() ||
+         (Is<VectorType>() && As<VectorType>()->type()->Is<U32Type>());
 }
 
 bool Type::is_signed_scalar_or_vector() {
-  return Is<I32Type>() || (IsVector() && AsVector()->type()->Is<I32Type>());
+  return Is<I32Type>() ||
+         (Is<VectorType>() && As<VectorType>()->type()->Is<I32Type>());
 }
 
 bool Type::is_integer_scalar_or_vector() {
   return is_unsigned_scalar_or_vector() || is_signed_scalar_or_vector();
 }
 
-const VectorType* Type::AsVector() const {
-  assert(IsVector());
-  return static_cast<const VectorType*>(this);
-}
-
 const VoidType* Type::AsVoid() const {
   assert(IsVoid());
   return static_cast<const VoidType*>(this);
 }
 
-VectorType* Type::AsVector() {
-  assert(IsVector());
-  return static_cast<VectorType*>(this);
-}
-
 VoidType* Type::AsVoid() {
   assert(IsVoid());
   return static_cast<VoidType*>(this);
diff --git a/src/ast/type/type.h b/src/ast/type/type.h
index a78f916..9c056d7 100644
--- a/src/ast/type/type.h
+++ b/src/ast/type/type.h
@@ -23,7 +23,6 @@
 namespace ast {
 namespace type {
 
-class VectorType;
 class VoidType;
 
 /// Supported memory layouts for calculating sizes
@@ -36,8 +35,6 @@
   Type(Type&&);
   ~Type() override;
 
-  /// @returns true if the type is a vec type
-  virtual bool IsVector() const;
   /// @returns true if the type is a void type
   virtual bool IsVoid() const;
 
@@ -95,13 +92,9 @@
   /// @returns true if this type is an integer scalar or vector
   bool is_integer_scalar_or_vector();
 
-  /// @returns the type as a vector type
-  const VectorType* AsVector() const;
   /// @returns the type as a void type
   const VoidType* AsVoid() const;
 
-  /// @returns the type as a vector type
-  VectorType* AsVector();
   /// @returns the type as a void type
   VoidType* AsVoid();
 
diff --git a/src/ast/type/u32_type_test.cc b/src/ast/type/u32_type_test.cc
index 5afb341..19802b5 100644
--- a/src/ast/type/u32_type_test.cc
+++ b/src/ast/type/u32_type_test.cc
@@ -25,6 +25,7 @@
 #include "src/ast/type/sampler_type.h"
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/texture_type.h"
+#include "src/ast/type/vector_type.h"
 
 namespace tint {
 namespace ast {
@@ -48,7 +49,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_FALSE(ty->Is<TextureType>());
   EXPECT_TRUE(ty->Is<U32Type>());
-  EXPECT_FALSE(ty->IsVector());
+  EXPECT_FALSE(ty->Is<VectorType>());
 }
 
 TEST_F(U32TypeTest, TypeName) {
diff --git a/src/ast/type/vector_type.cc b/src/ast/type/vector_type.cc
index 973471f..14614c3 100644
--- a/src/ast/type/vector_type.cc
+++ b/src/ast/type/vector_type.cc
@@ -31,10 +31,6 @@
 
 VectorType::~VectorType() = default;
 
-bool VectorType::IsVector() const {
-  return true;
-}
-
 std::string VectorType::type_name() const {
   return "__vec_" + std::to_string(size_) + subtype_->type_name();
 }
diff --git a/src/ast/type/vector_type.h b/src/ast/type/vector_type.h
index 257d27c..c09d75e 100644
--- a/src/ast/type/vector_type.h
+++ b/src/ast/type/vector_type.h
@@ -34,9 +34,6 @@
   VectorType(VectorType&&);
   ~VectorType() override;
 
-  /// @returns true if the type is a vector type
-  bool IsVector() const override;
-
   /// @returns the type of the vector elements
   Type* type() const { return subtype_; }
   /// @returns the size of the vector
diff --git a/src/ast/type/vector_type_test.cc b/src/ast/type/vector_type_test.cc
index 8940ba9..14c88cd 100644
--- a/src/ast/type/vector_type_test.cc
+++ b/src/ast/type/vector_type_test.cc
@@ -56,7 +56,7 @@
   EXPECT_FALSE(ty->Is<StructType>());
   EXPECT_FALSE(ty->Is<TextureType>());
   EXPECT_FALSE(ty->Is<U32Type>());
-  EXPECT_TRUE(ty->IsVector());
+  EXPECT_TRUE(ty->Is<VectorType>());
 }
 
 TEST_F(VectorTypeTest, TypeName) {
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index b4da984..678b1f6 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -391,8 +391,8 @@
       base_type = base_type->As<ast::type::ArrayType>()->type();
     } else if (base_type->Is<ast::type::MatrixType>()) {
       base_type = base_type->As<ast::type::MatrixType>()->type();
-    } else if (base_type->IsVector()) {
-      base_type = base_type->AsVector()->type();
+    } else if (base_type->Is<ast::type::VectorType>()) {
+      base_type = base_type->As<ast::type::VectorType>()->type();
     }
 
     if (base_type->Is<ast::type::F32Type>()) {
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index e008eb7..d206534 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -3206,7 +3206,7 @@
   // Generate an ast::TypeConstructor expression.
   // Assume the literal indices are valid, and there is a valid number of them.
   ast::type::VectorType* result_type =
-      parser_impl_.ConvertType(inst.type_id())->AsVector();
+      parser_impl_.ConvertType(inst.type_id())->As<ast::type::VectorType>();
   ast::ExpressionList values;
   for (uint32_t i = 2; i < inst.NumInOperands(); ++i) {
     const auto index = inst.GetSingleWordInOperand(i);
@@ -3598,7 +3598,7 @@
   // - you can't select over pointers or pointer vectors, unless you also have
   //   a VariablePointers* capability, which is not allowed in by WebGPU.
   auto* op_ty = operand1.type;
-  if (op_ty->IsVector() || op_ty->is_float_scalar() ||
+  if (op_ty->Is<ast::type::VectorType>() || op_ty->is_float_scalar() ||
       op_ty->is_integer_scalar() || op_ty->Is<ast::type::BoolType>()) {
     ast::ExpressionList params;
     params.push_back(operand1.expr);
@@ -3829,8 +3829,8 @@
   uint32_t num_coords_supplied = 0;
   if (raw_coords.type->Is<ast::type::F32Type>()) {
     num_coords_supplied = 1;
-  } else if (raw_coords.type->IsVector()) {
-    num_coords_supplied = raw_coords.type->AsVector()->size();
+  } else if (raw_coords.type->Is<ast::type::VectorType>()) {
+    num_coords_supplied = raw_coords.type->As<ast::type::VectorType>()->size();
   }
   if (num_coords_supplied == 0) {
     Fail() << "bad or unsupported coordinate type for image access: "
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index 56c2f53..eb0c8fc 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -1351,8 +1351,8 @@
     return create<ast::ScalarConstructorExpression>(
         create<ast::FloatLiteral>(type, 0.0f));
   }
-  if (type->IsVector()) {
-    const auto* vec_ty = type->AsVector();
+  if (type->Is<ast::type::VectorType>()) {
+    const auto* vec_ty = type->As<ast::type::VectorType>();
     ast::ExpressionList ast_components;
     for (size_t i = 0; i < vec_ty->size(); ++i) {
       ast_components.emplace_back(MakeNullValue(vec_ty->type()));
@@ -1450,7 +1450,7 @@
       other->Is<ast::type::I32Type>()) {
     return i32;
   }
-  auto* vec_ty = other->AsVector();
+  auto* vec_ty = other->As<ast::type::VectorType>();
   if (vec_ty) {
     return ast_module_.create<ast::type::VectorType>(i32, vec_ty->size());
   }
@@ -1469,7 +1469,7 @@
       other->Is<ast::type::I32Type>()) {
     return u32;
   }
-  auto* vec_ty = other->AsVector();
+  auto* vec_ty = other->As<ast::type::VectorType>();
   if (vec_ty) {
     return ast_module_.create<ast::type::VectorType>(u32, vec_ty->size());
   }
diff --git a/src/reader/spirv/parser_impl_convert_type_test.cc b/src/reader/spirv/parser_impl_convert_type_test.cc
index 4a5100f..966a43b 100644
--- a/src/reader/spirv/parser_impl_convert_type_test.cc
+++ b/src/reader/spirv/parser_impl_convert_type_test.cc
@@ -171,19 +171,22 @@
   EXPECT_TRUE(p->BuildInternalModule());
 
   auto* v2xf32 = p->ConvertType(20);
-  EXPECT_TRUE(v2xf32->IsVector());
-  EXPECT_TRUE(v2xf32->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(v2xf32->AsVector()->size(), 2u);
+  EXPECT_TRUE(v2xf32->Is<ast::type::VectorType>());
+  EXPECT_TRUE(
+      v2xf32->As<ast::type::VectorType>()->type()->Is<ast::type::F32Type>());
+  EXPECT_EQ(v2xf32->As<ast::type::VectorType>()->size(), 2u);
 
   auto* v3xf32 = p->ConvertType(30);
-  EXPECT_TRUE(v3xf32->IsVector());
-  EXPECT_TRUE(v3xf32->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(v3xf32->AsVector()->size(), 3u);
+  EXPECT_TRUE(v3xf32->Is<ast::type::VectorType>());
+  EXPECT_TRUE(
+      v3xf32->As<ast::type::VectorType>()->type()->Is<ast::type::F32Type>());
+  EXPECT_EQ(v3xf32->As<ast::type::VectorType>()->size(), 3u);
 
   auto* v4xf32 = p->ConvertType(40);
-  EXPECT_TRUE(v4xf32->IsVector());
-  EXPECT_TRUE(v4xf32->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(v4xf32->AsVector()->size(), 4u);
+  EXPECT_TRUE(v4xf32->Is<ast::type::VectorType>());
+  EXPECT_TRUE(
+      v4xf32->As<ast::type::VectorType>()->type()->Is<ast::type::F32Type>());
+  EXPECT_EQ(v4xf32->As<ast::type::VectorType>()->size(), 4u);
 
   EXPECT_TRUE(p->error().empty());
 }
@@ -198,19 +201,22 @@
   EXPECT_TRUE(p->BuildInternalModule());
 
   auto* v2xi32 = p->ConvertType(20);
-  EXPECT_TRUE(v2xi32->IsVector());
-  EXPECT_TRUE(v2xi32->AsVector()->type()->Is<ast::type::I32Type>());
-  EXPECT_EQ(v2xi32->AsVector()->size(), 2u);
+  EXPECT_TRUE(v2xi32->Is<ast::type::VectorType>());
+  EXPECT_TRUE(
+      v2xi32->As<ast::type::VectorType>()->type()->Is<ast::type::I32Type>());
+  EXPECT_EQ(v2xi32->As<ast::type::VectorType>()->size(), 2u);
 
   auto* v3xi32 = p->ConvertType(30);
-  EXPECT_TRUE(v3xi32->IsVector());
-  EXPECT_TRUE(v3xi32->AsVector()->type()->Is<ast::type::I32Type>());
-  EXPECT_EQ(v3xi32->AsVector()->size(), 3u);
+  EXPECT_TRUE(v3xi32->Is<ast::type::VectorType>());
+  EXPECT_TRUE(
+      v3xi32->As<ast::type::VectorType>()->type()->Is<ast::type::I32Type>());
+  EXPECT_EQ(v3xi32->As<ast::type::VectorType>()->size(), 3u);
 
   auto* v4xi32 = p->ConvertType(40);
-  EXPECT_TRUE(v4xi32->IsVector());
-  EXPECT_TRUE(v4xi32->AsVector()->type()->Is<ast::type::I32Type>());
-  EXPECT_EQ(v4xi32->AsVector()->size(), 4u);
+  EXPECT_TRUE(v4xi32->Is<ast::type::VectorType>());
+  EXPECT_TRUE(
+      v4xi32->As<ast::type::VectorType>()->type()->Is<ast::type::I32Type>());
+  EXPECT_EQ(v4xi32->As<ast::type::VectorType>()->size(), 4u);
 
   EXPECT_TRUE(p->error().empty());
 }
@@ -225,19 +231,22 @@
   EXPECT_TRUE(p->BuildInternalModule());
 
   auto* v2xu32 = p->ConvertType(20);
-  EXPECT_TRUE(v2xu32->IsVector());
-  EXPECT_TRUE(v2xu32->AsVector()->type()->Is<ast::type::U32Type>());
-  EXPECT_EQ(v2xu32->AsVector()->size(), 2u);
+  EXPECT_TRUE(v2xu32->Is<ast::type::VectorType>());
+  EXPECT_TRUE(
+      v2xu32->As<ast::type::VectorType>()->type()->Is<ast::type::U32Type>());
+  EXPECT_EQ(v2xu32->As<ast::type::VectorType>()->size(), 2u);
 
   auto* v3xu32 = p->ConvertType(30);
-  EXPECT_TRUE(v3xu32->IsVector());
-  EXPECT_TRUE(v3xu32->AsVector()->type()->Is<ast::type::U32Type>());
-  EXPECT_EQ(v3xu32->AsVector()->size(), 3u);
+  EXPECT_TRUE(v3xu32->Is<ast::type::VectorType>());
+  EXPECT_TRUE(
+      v3xu32->As<ast::type::VectorType>()->type()->Is<ast::type::U32Type>());
+  EXPECT_EQ(v3xu32->As<ast::type::VectorType>()->size(), 3u);
 
   auto* v4xu32 = p->ConvertType(40);
-  EXPECT_TRUE(v4xu32->IsVector());
-  EXPECT_TRUE(v4xu32->AsVector()->type()->Is<ast::type::U32Type>());
-  EXPECT_EQ(v4xu32->AsVector()->size(), 4u);
+  EXPECT_TRUE(v4xu32->Is<ast::type::VectorType>());
+  EXPECT_TRUE(
+      v4xu32->As<ast::type::VectorType>()->type()->Is<ast::type::U32Type>());
+  EXPECT_EQ(v4xu32->As<ast::type::VectorType>()->size(), 4u);
 
   EXPECT_TRUE(p->error().empty());
 }
diff --git a/src/reader/wgsl/parser_impl_const_expr_test.cc b/src/reader/wgsl/parser_impl_const_expr_test.cc
index 0635a72..4135515 100644
--- a/src/reader/wgsl/parser_impl_const_expr_test.cc
+++ b/src/reader/wgsl/parser_impl_const_expr_test.cc
@@ -35,8 +35,8 @@
   ASSERT_TRUE(e->AsConstructor()->IsTypeConstructor());
 
   auto* t = e->AsConstructor()->AsTypeConstructor();
-  ASSERT_TRUE(t->type()->IsVector());
-  EXPECT_EQ(t->type()->AsVector()->size(), 2u);
+  ASSERT_TRUE(t->type()->Is<ast::type::VectorType>());
+  EXPECT_EQ(t->type()->As<ast::type::VectorType>()->size(), 2u);
 
   ASSERT_EQ(t->values().size(), 2u);
   auto& v = t->values();
diff --git a/src/reader/wgsl/parser_impl_type_decl_test.cc b/src/reader/wgsl/parser_impl_type_decl_test.cc
index cc27ef3..24ac3cd 100644
--- a/src/reader/wgsl/parser_impl_type_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_type_decl_test.cc
@@ -151,8 +151,8 @@
   EXPECT_FALSE(t.errored);
   ASSERT_NE(t.value, nullptr) << p->error();
   ASSERT_FALSE(p->has_error());
-  EXPECT_TRUE(t->IsVector());
-  EXPECT_EQ(t->AsVector()->size(), params.count);
+  EXPECT_TRUE(t->Is<ast::type::VectorType>());
+  EXPECT_EQ(t->As<ast::type::VectorType>()->size(), params.count);
 }
 INSTANTIATE_TEST_SUITE_P(ParserImplTest,
                          VecTest,
@@ -256,10 +256,10 @@
   ASSERT_TRUE(t->Is<ast::type::PointerType>());
 
   auto* ptr = t->As<ast::type::PointerType>();
-  ASSERT_TRUE(ptr->type()->IsVector());
+  ASSERT_TRUE(ptr->type()->Is<ast::type::VectorType>());
   ASSERT_EQ(ptr->storage_class(), ast::StorageClass::kFunction);
 
-  auto* vec = ptr->type()->AsVector();
+  auto* vec = ptr->type()->As<ast::type::VectorType>();
   ASSERT_EQ(vec->size(), 2u);
   ASSERT_TRUE(vec->type()->Is<ast::type::F32Type>());
 }
diff --git a/src/transform/bound_array_accessors_transform.cc b/src/transform/bound_array_accessors_transform.cc
index dd9ec6f..61e4a4a 100644
--- a/src/transform/bound_array_accessors_transform.cc
+++ b/src/transform/bound_array_accessors_transform.cc
@@ -185,13 +185,15 @@
 
   auto* ret_type = expr->array()->result_type()->UnwrapAll();
   if (!ret_type->Is<ast::type::ArrayType>() &&
-      !ret_type->Is<ast::type::MatrixType>() && !ret_type->IsVector()) {
+      !ret_type->Is<ast::type::MatrixType>() &&
+      !ret_type->Is<ast::type::VectorType>()) {
     return true;
   }
 
-  if (ret_type->IsVector() || ret_type->Is<ast::type::ArrayType>()) {
-    uint32_t size = ret_type->IsVector()
-                        ? ret_type->AsVector()->size()
+  if (ret_type->Is<ast::type::VectorType>() ||
+      ret_type->Is<ast::type::ArrayType>()) {
+    uint32_t size = ret_type->Is<ast::type::VectorType>()
+                        ? ret_type->As<ast::type::VectorType>()->size()
                         : ret_type->As<ast::type::ArrayType>()->size();
     if (size == 0) {
       error_ = "invalid 0 size for array or vector";
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index 8f5ab1d..964a2fb 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -337,8 +337,8 @@
   ast::type::Type* ret = nullptr;
   if (parent_type->Is<ast::type::ArrayType>()) {
     ret = parent_type->As<ast::type::ArrayType>()->type();
-  } else if (parent_type->IsVector()) {
-    ret = parent_type->AsVector()->type();
+  } else if (parent_type->Is<ast::type::VectorType>()) {
+    ret = parent_type->As<ast::type::VectorType>()->type();
   } else if (parent_type->Is<ast::type::MatrixType>()) {
     auto* m = parent_type->As<ast::type::MatrixType>();
     ret = mod_->create<ast::type::VectorType>(m->type(), m->rows());
@@ -540,9 +540,9 @@
     auto* bool_type = mod_->create<ast::type::BoolType>();
 
     auto* param_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
-    if (param_type->IsVector()) {
+    if (param_type->Is<ast::type::VectorType>()) {
       expr->func()->set_result_type(mod_->create<ast::type::VectorType>(
-          bool_type, param_type->AsVector()->size()));
+          bool_type, param_type->As<ast::type::VectorType>()->size()));
     } else {
       expr->func()->set_result_type(bool_type);
     }
@@ -703,14 +703,16 @@
 
     auto* param0_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
     auto* param1_type = expr->params()[1]->result_type()->UnwrapPtrIfNeeded();
-    if (!param0_type->IsVector() || !param1_type->IsVector()) {
+    if (!param0_type->Is<ast::type::VectorType>() ||
+        !param1_type->Is<ast::type::VectorType>()) {
       set_error(expr->source(), "invalid parameter type for " + ident->name());
       return false;
     }
 
     expr->func()->set_result_type(mod_->create<ast::type::MatrixType>(
-        mod_->create<ast::type::F32Type>(), param0_type->AsVector()->size(),
-        param1_type->AsVector()->size()));
+        mod_->create<ast::type::F32Type>(),
+        param0_type->As<ast::type::VectorType>()->size(),
+        param1_type->As<ast::type::VectorType>()->size()));
     return true;
   }
   if (ident->intrinsic() == ast::Intrinsic::kSelect) {
@@ -786,7 +788,8 @@
           return false;
         }
         if (data->vector_size > 0 &&
-            result_types.back()->AsVector()->size() != data->vector_size) {
+            result_types.back()->As<ast::type::VectorType>()->size() !=
+                data->vector_size) {
           set_error(expr->source(), "incorrect vector size for " +
                                         ident->name() + ". " + "Requires " +
                                         std::to_string(data->vector_size) +
@@ -817,9 +820,10 @@
   // provided.
   if (ident->intrinsic() == ast::Intrinsic::kLength ||
       ident->intrinsic() == ast::Intrinsic::kDistance) {
-    expr->func()->set_result_type(result_types[0]->is_float_scalar()
-                                      ? result_types[0]
-                                      : result_types[0]->AsVector()->type());
+    expr->func()->set_result_type(
+        result_types[0]->is_float_scalar()
+            ? result_types[0]
+            : result_types[0]->As<ast::type::VectorType>()->type());
     return true;
   }
   // The determinant returns the component type of the columns
@@ -1054,8 +1058,8 @@
       ret = mod_->create<ast::type::PointerType>(
           ret, res->As<ast::type::PointerType>()->storage_class());
     }
-  } else if (data_type->IsVector()) {
-    auto* vec = data_type->AsVector();
+  } else if (data_type->Is<ast::type::VectorType>()) {
+    auto* vec = data_type->As<ast::type::VectorType>();
 
     auto size = expr->member()->name().size();
     if (size == 1) {
@@ -1103,9 +1107,9 @@
       expr->IsLessThanEqual() || expr->IsGreaterThanEqual()) {
     auto* bool_type = mod_->create<ast::type::BoolType>();
     auto* param_type = expr->lhs()->result_type()->UnwrapPtrIfNeeded();
-    if (param_type->IsVector()) {
+    if (param_type->Is<ast::type::VectorType>()) {
       expr->set_result_type(mod_->create<ast::type::VectorType>(
-          bool_type, param_type->AsVector()->size()));
+          bool_type, param_type->As<ast::type::VectorType>()->size()));
     } else {
       expr->set_result_type(bool_type);
     }
@@ -1124,11 +1128,13 @@
           lhs_type->As<ast::type::MatrixType>()->rows(),
           rhs_type->As<ast::type::MatrixType>()->columns()));
 
-    } else if (lhs_type->Is<ast::type::MatrixType>() && rhs_type->IsVector()) {
+    } else if (lhs_type->Is<ast::type::MatrixType>() &&
+               rhs_type->Is<ast::type::VectorType>()) {
       auto* mat = lhs_type->As<ast::type::MatrixType>();
       expr->set_result_type(
           mod_->create<ast::type::VectorType>(mat->type(), mat->rows()));
-    } else if (lhs_type->IsVector() && rhs_type->Is<ast::type::MatrixType>()) {
+    } else if (lhs_type->Is<ast::type::VectorType>() &&
+               rhs_type->Is<ast::type::MatrixType>()) {
       auto* mat = rhs_type->As<ast::type::MatrixType>();
       expr->set_result_type(
           mod_->create<ast::type::VectorType>(mat->type(), mat->columns()));
@@ -1138,12 +1144,13 @@
     } else if (rhs_type->Is<ast::type::MatrixType>()) {
       // scalar * matrix
       expr->set_result_type(rhs_type);
-    } else if (lhs_type->IsVector() && rhs_type->IsVector()) {
+    } else if (lhs_type->Is<ast::type::VectorType>() &&
+               rhs_type->Is<ast::type::VectorType>()) {
       expr->set_result_type(lhs_type);
-    } else if (lhs_type->IsVector()) {
+    } else if (lhs_type->Is<ast::type::VectorType>()) {
       // Vector * scalar
       expr->set_result_type(lhs_type);
-    } else if (rhs_type->IsVector()) {
+    } else if (rhs_type->Is<ast::type::VectorType>()) {
       // Scalar * vector
       expr->set_result_type(rhs_type);
     } else {
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index dd3784d..5357c82 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -512,8 +512,8 @@
   ASSERT_TRUE(acc.result_type()->Is<ast::type::PointerType>());
 
   auto* ptr = acc.result_type()->As<ast::type::PointerType>();
-  ASSERT_TRUE(ptr->type()->IsVector());
-  EXPECT_EQ(ptr->type()->AsVector()->size(), 3u);
+  ASSERT_TRUE(ptr->type()->Is<ast::type::VectorType>());
+  EXPECT_EQ(ptr->type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Matrix_BothDimensions) {
@@ -681,9 +681,12 @@
 
   EXPECT_TRUE(td()->DetermineResultType(&tc));
   ASSERT_NE(tc.result_type(), nullptr);
-  ASSERT_TRUE(tc.result_type()->IsVector());
-  EXPECT_TRUE(tc.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(tc.result_type()->AsVector()->size(), 3u);
+  ASSERT_TRUE(tc.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(tc.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::F32Type>());
+  EXPECT_EQ(tc.result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_F(TypeDeterminerTest, Expr_Identifier_GlobalVariable) {
@@ -1029,9 +1032,12 @@
   ast::MemberAccessorExpression mem(ident, swizzle);
   EXPECT_TRUE(td()->DetermineResultType(&mem)) << td()->error();
   ASSERT_NE(mem.result_type(), nullptr);
-  ASSERT_TRUE(mem.result_type()->IsVector());
-  EXPECT_TRUE(mem.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(mem.result_type()->AsVector()->size(), 2u);
+  ASSERT_TRUE(mem.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(mem.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::F32Type>());
+  EXPECT_EQ(mem.result_type()->As<ast::type::VectorType>()->size(), 2u);
 }
 
 TEST_F(TypeDeterminerTest, Expr_MemberAccessor_VectorSwizzle_SingleElement) {
@@ -1124,9 +1130,12 @@
   EXPECT_TRUE(td()->DetermineResultType(&mem)) << td()->error();
 
   ASSERT_NE(mem.result_type(), nullptr);
-  ASSERT_TRUE(mem.result_type()->IsVector());
-  EXPECT_TRUE(mem.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(mem.result_type()->AsVector()->size(), 2u);
+  ASSERT_TRUE(mem.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(mem.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::F32Type>());
+  EXPECT_EQ(mem.result_type()->As<ast::type::VectorType>()->size(), 2u);
 }
 
 using Expr_Binary_BitwiseTest = TypeDeterminerTestWithParam<ast::BinaryOp>;
@@ -1166,9 +1175,12 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsVector());
-  EXPECT_TRUE(expr.result_type()->AsVector()->type()->Is<ast::type::I32Type>());
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 3u);
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(expr.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::I32Type>());
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 INSTANTIATE_TEST_SUITE_P(TypeDeterminerTest,
                          Expr_Binary_BitwiseTest,
@@ -1220,10 +1232,12 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsVector());
-  EXPECT_TRUE(
-      expr.result_type()->AsVector()->type()->Is<ast::type::BoolType>());
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 3u);
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(expr.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::BoolType>());
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 INSTANTIATE_TEST_SUITE_P(TypeDeterminerTest,
                          Expr_Binary_LogicalTest,
@@ -1267,10 +1281,12 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsVector());
-  EXPECT_TRUE(
-      expr.result_type()->AsVector()->type()->Is<ast::type::BoolType>());
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 3u);
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(expr.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::BoolType>());
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 INSTANTIATE_TEST_SUITE_P(TypeDeterminerTest,
                          Expr_Binary_CompareTest,
@@ -1319,9 +1335,12 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsVector());
-  EXPECT_TRUE(expr.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 3u);
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(expr.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::F32Type>());
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Scalar_Vector) {
@@ -1344,9 +1363,12 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsVector());
-  EXPECT_TRUE(expr.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 3u);
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(expr.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::F32Type>());
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Vector_Vector) {
@@ -1366,9 +1388,12 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsVector());
-  EXPECT_TRUE(expr.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 3u);
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(expr.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::F32Type>());
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Matrix_Scalar) {
@@ -1448,9 +1473,12 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsVector());
-  EXPECT_TRUE(expr.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 3u);
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(expr.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::F32Type>());
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Vector_Matrix) {
@@ -1474,9 +1502,12 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsVector());
-  EXPECT_TRUE(expr.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 2u);
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(expr.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::F32Type>());
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 2u);
 }
 
 TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Matrix_Matrix) {
@@ -1551,9 +1582,12 @@
   EXPECT_TRUE(td()->DetermineResultType(&expr));
 
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsVector());
-  EXPECT_TRUE(expr.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 4u);
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(expr.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::F32Type>());
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 4u);
 }
 
 TEST_P(IntrinsicDerivativeTest, MissingParam) {
@@ -1655,10 +1689,12 @@
   EXPECT_TRUE(td()->DetermineResultType(&expr));
 
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsVector());
-  EXPECT_TRUE(
-      expr.result_type()->AsVector()->type()->Is<ast::type::BoolType>());
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 3u);
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(expr.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::BoolType>());
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(Intrinsic_FloatMethod, Scalar) {
@@ -1815,18 +1851,24 @@
   EXPECT_TRUE(td()->DetermineResultType(&expr));
 
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsVector());
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
   if (type == TextureType::kF32) {
-    EXPECT_TRUE(
-        expr.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
+    EXPECT_TRUE(expr.result_type()
+                    ->As<ast::type::VectorType>()
+                    ->type()
+                    ->Is<ast::type::F32Type>());
   } else if (type == TextureType::kI32) {
-    EXPECT_TRUE(
-        expr.result_type()->AsVector()->type()->Is<ast::type::I32Type>());
+    EXPECT_TRUE(expr.result_type()
+                    ->As<ast::type::VectorType>()
+                    ->type()
+                    ->Is<ast::type::I32Type>());
   } else {
-    EXPECT_TRUE(
-        expr.result_type()->AsVector()->type()->Is<ast::type::U32Type>());
+    EXPECT_TRUE(expr.result_type()
+                    ->As<ast::type::VectorType>()
+                    ->type()
+                    ->Is<ast::type::U32Type>());
   }
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 4u);
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 4u);
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -1888,18 +1930,24 @@
   EXPECT_TRUE(td()->DetermineResultType(&expr));
 
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsVector());
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
   if (type == TextureType::kF32) {
-    EXPECT_TRUE(
-        expr.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
+    EXPECT_TRUE(expr.result_type()
+                    ->As<ast::type::VectorType>()
+                    ->type()
+                    ->Is<ast::type::F32Type>());
   } else if (type == TextureType::kI32) {
-    EXPECT_TRUE(
-        expr.result_type()->AsVector()->type()->Is<ast::type::I32Type>());
+    EXPECT_TRUE(expr.result_type()
+                    ->As<ast::type::VectorType>()
+                    ->type()
+                    ->Is<ast::type::I32Type>());
   } else {
-    EXPECT_TRUE(
-        expr.result_type()->AsVector()->type()->Is<ast::type::U32Type>());
+    EXPECT_TRUE(expr.result_type()
+                    ->As<ast::type::VectorType>()
+                    ->type()
+                    ->Is<ast::type::U32Type>());
   }
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 4u);
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 4u);
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -1956,9 +2004,12 @@
   EXPECT_TRUE(td()->Determine());
   EXPECT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  EXPECT_TRUE(expr.result_type()->IsVector());
-  EXPECT_EQ(expr.result_type()->AsVector()->size(), 3u);
-  EXPECT_TRUE(expr.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
+  EXPECT_TRUE(expr.result_type()->Is<ast::type::VectorType>());
+  EXPECT_EQ(expr.result_type()->As<ast::type::VectorType>()->size(), 3u);
+  EXPECT_TRUE(expr.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::F32Type>());
 }
 
 TEST_F(TypeDeterminerTest, Intrinsic_Select_TooFewParams) {
@@ -2093,9 +2144,12 @@
   ast::UnaryOpExpression der(op, create<ast::IdentifierExpression>("ident"));
   EXPECT_TRUE(td()->DetermineResultType(&der));
   ASSERT_NE(der.result_type(), nullptr);
-  ASSERT_TRUE(der.result_type()->IsVector());
-  EXPECT_TRUE(der.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(der.result_type()->AsVector()->size(), 4u);
+  ASSERT_TRUE(der.result_type()->Is<ast::type::VectorType>());
+  EXPECT_TRUE(der.result_type()
+                  ->As<ast::type::VectorType>()
+                  ->type()
+                  ->Is<ast::type::F32Type>());
+  EXPECT_EQ(der.result_type()->As<ast::type::VectorType>()->size(), 4u);
 }
 INSTANTIATE_TEST_SUITE_P(TypeDeterminerTest,
                          UnaryOpExpressionTest,
@@ -2294,7 +2348,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_float_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_SingleParamTest, Error_Integer) {
@@ -2418,7 +2472,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_float_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_SingleParam_FloatOrInt_Test, Sint_Scalar) {
@@ -2463,7 +2517,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_signed_integer_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_SingleParam_FloatOrInt_Test, Uint_Scalar) {
@@ -2508,7 +2562,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_unsigned_integer_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_SingleParam_FloatOrInt_Test, Error_Bool) {
@@ -2708,7 +2762,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_float_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_TwoParamTest, Error_Integer) {
@@ -3045,7 +3099,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_float_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_F(TypeDeterminerTest, ImportData_Cross_Error_Scalar) {
@@ -3236,7 +3290,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_float_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_ThreeParamTest, Error_Integer) {
@@ -3476,7 +3530,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_float_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_ThreeParam_FloatOrInt_Test, Sint_Scalar) {
@@ -3543,7 +3597,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_signed_integer_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_ThreeParam_FloatOrInt_Test, Uint_Scalar) {
@@ -3610,7 +3664,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_unsigned_integer_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_ThreeParam_FloatOrInt_Test, Error_Bool) {
@@ -3824,7 +3878,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_signed_integer_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_Int_SingleParamTest, Error_Float) {
@@ -3980,7 +4034,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_signed_integer_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_FloatOrInt_TwoParamTest, Vector_Unsigned) {
@@ -4016,7 +4070,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_unsigned_integer_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_FloatOrInt_TwoParamTest, Vector_Float) {
@@ -4052,7 +4106,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
   EXPECT_TRUE(ident->result_type()->is_float_vector());
-  EXPECT_EQ(ident->result_type()->AsVector()->size(), 3u);
+  EXPECT_EQ(ident->result_type()->As<ast::type::VectorType>()->size(), 3u);
 }
 
 TEST_P(ImportData_FloatOrInt_TwoParamTest, Error_Bool) {
@@ -4586,8 +4640,9 @@
 
   switch (param.texture_kind) {
     case ast::intrinsic::test::TextureKind::kRegular:
-      ASSERT_TRUE(call.result_type()->IsVector());
-      EXPECT_EQ(call.result_type()->AsVector()->type(), datatype);
+      ASSERT_TRUE(call.result_type()->Is<ast::type::VectorType>());
+      EXPECT_EQ(call.result_type()->As<ast::type::VectorType>()->type(),
+                datatype);
       break;
 
     case ast::intrinsic::test::TextureKind::kDepth:
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index 74c3781..b0e3f90 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -377,8 +377,10 @@
   // Multiplying by a matrix requires the use of `mul` in order to get the
   // type of multiply we desire.
   if (expr->op() == ast::BinaryOp::kMultiply &&
-      ((lhs_type->IsVector() && rhs_type->Is<ast::type::MatrixType>()) ||
-       (lhs_type->Is<ast::type::MatrixType>() && rhs_type->IsVector()) ||
+      ((lhs_type->Is<ast::type::VectorType>() &&
+        rhs_type->Is<ast::type::MatrixType>()) ||
+       (lhs_type->Is<ast::type::MatrixType>() &&
+        rhs_type->Is<ast::type::VectorType>()) ||
        (lhs_type->Is<ast::type::MatrixType>() &&
         rhs_type->Is<ast::type::MatrixType>()))) {
     out << "mul(";
@@ -614,13 +616,14 @@
       // out << "(";
 
       // auto param1_type = params[1]->result_type()->UnwrapPtrIfNeeded();
-      // if (!param1_type->IsVector()) {
+      // if (!param1_type->Is<ast::type::VectorType>()) {
       //   error_ = "invalid param type in outer_product got: " +
       //            param1_type->type_name();
       //   return false;
       // }
 
-      // for (uint32_t i = 0; i < param1_type->AsVector()->size(); ++i) {
+      // for (uint32_t i = 0; i <
+      // param1_type->As<ast::type::VectorType>()->size(); ++i) {
       //   if (i > 0) {
       //     out << ", ";
       //   }
@@ -1556,8 +1559,8 @@
     out << "0";
   } else if (type->Is<ast::type::U32Type>()) {
     out << "0u";
-  } else if (type->IsVector()) {
-    return EmitZeroValue(out, type->AsVector()->type());
+  } else if (type->Is<ast::type::VectorType>()) {
+    return EmitZeroValue(out, type->As<ast::type::VectorType>()->type());
   } else if (type->Is<ast::type::MatrixType>()) {
     auto* mat = type->As<ast::type::MatrixType>();
     for (uint32_t i = 0; i < (mat->rows() * mat->columns()); i++) {
@@ -1697,7 +1700,7 @@
         }
         out << str_member->offset();
 
-      } else if (res_type->IsVector()) {
+      } else if (res_type->Is<ast::type::VectorType>()) {
         // This must be a single element swizzle if we've got a vector at this
         // point.
         if (mem->member()->name().size() != 1) {
@@ -1726,7 +1729,7 @@
       out << "(";
       if (ary_type->Is<ast::type::ArrayType>()) {
         out << ary_type->As<ast::type::ArrayType>()->array_stride();
-      } else if (ary_type->IsVector()) {
+      } else if (ary_type->Is<ast::type::VectorType>()) {
         // TODO(dsinclair): This is a hack. Our vectors can only be f32, i32
         // or u32 which are all 4 bytes. When we get f16 or other types we'll
         // have to ask the type for the byte size.
@@ -1773,8 +1776,9 @@
   bool is_store = rhs != nullptr;
 
   std::string access_method = is_store ? "Store" : "Load";
-  if (result_type->IsVector()) {
-    access_method += std::to_string(result_type->AsVector()->size());
+  if (result_type->Is<ast::type::VectorType>()) {
+    access_method +=
+        std::to_string(result_type->As<ast::type::VectorType>()->size());
   } else if (result_type->Is<ast::type::MatrixType>()) {
     access_method +=
         std::to_string(result_type->As<ast::type::MatrixType>()->rows());
@@ -1891,7 +1895,8 @@
   auto* data_type = structure->result_type()->UnwrapAll();
   // If the data is a multi-element swizzle then we will not load the swizzle
   // portion through the Load command.
-  if (data_type->IsVector() && expr->member()->name().size() > 1) {
+  if (data_type->Is<ast::type::VectorType>() &&
+      expr->member()->name().size() > 1) {
     return false;
   }
 
@@ -2127,8 +2132,8 @@
 
   } else if (type->Is<ast::type::U32Type>()) {
     out << "uint";
-  } else if (type->IsVector()) {
-    auto* vec = type->AsVector();
+  } else if (type->Is<ast::type::VectorType>()) {
+    auto* vec = type->As<ast::type::VectorType>();
     auto size = vec->size();
     if (vec->type()->Is<ast::type::F32Type>() && size >= 1 && size <= 4) {
       out << "float" << size;
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index b90d610..ee8d27e 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -242,8 +242,8 @@
     count = adjust_for_alignment(count, largest_alignment);
     return count;
   }
-  if (type->IsVector()) {
-    auto* vec = type->AsVector();
+  if (type->Is<ast::type::VectorType>()) {
+    auto* vec = type->As<ast::type::VectorType>();
     uint32_t type_size = calculate_alignment_size(vec->type());
     if (vec->size() == 2) {
       return 2 * type_size;
@@ -519,13 +519,14 @@
       // out_ << "(";
 
       // auto param1_type = params[1]->result_type()->UnwrapPtrIfNeeded();
-      // if (!param1_type->IsVector()) {
+      // if (!param1_type->Is<ast::type::VectorType>()) {
       //   error_ = "invalid param type in outer_product got: " +
       //            param1_type->type_name();
       //   return false;
       // }
 
-      // for (uint32_t i = 0; i < param1_type->AsVector()->size(); ++i) {
+      // for (uint32_t i = 0; i <
+      // param1_type->As<ast::type::VectorType>()->size(); ++i) {
       //   if (i > 0) {
       //     out_ << ", ";
       //   }
@@ -937,8 +938,8 @@
     out_ << "0";
   } else if (type->Is<ast::type::U32Type>()) {
     out_ << "0u";
-  } else if (type->IsVector()) {
-    return EmitZeroValue(type->AsVector()->type());
+  } else if (type->Is<ast::type::VectorType>()) {
+    return EmitZeroValue(type->As<ast::type::VectorType>()->type());
   } else if (type->Is<ast::type::MatrixType>()) {
     return EmitZeroValue(type->As<ast::type::MatrixType>()->type());
   } else if (type->Is<ast::type::ArrayType>()) {
@@ -1911,8 +1912,8 @@
 
   } else if (type->Is<ast::type::U32Type>()) {
     out_ << "uint";
-  } else if (type->IsVector()) {
-    auto* vec = type->AsVector();
+  } else if (type->Is<ast::type::VectorType>()) {
+    auto* vec = type->As<ast::type::VectorType>();
     if (!EmitType(vec->type(), "")) {
       return false;
     }
diff --git a/src/writer/pack_coord_arrayidx.cc b/src/writer/pack_coord_arrayidx.cc
index 3384ee6..8004c0a 100644
--- a/src/writer/pack_coord_arrayidx.cc
+++ b/src/writer/pack_coord_arrayidx.cc
@@ -33,7 +33,7 @@
     return nullptr;
   }
   auto* type_constructor = constructor->AsTypeConstructor();
-  if (!type_constructor->type()->IsVector()) {
+  if (!type_constructor->type()->Is<ast::type::VectorType>()) {
     return nullptr;
   }
   return type_constructor;
@@ -47,8 +47,8 @@
     std::function<bool(ast::TypeConstructorExpression*)> callback) {
   uint32_t packed_size;
   ast::type::Type* packed_el_ty;  // Currenly must be f32.
-  if (coords->result_type()->IsVector()) {
-    auto* vec = coords->result_type()->AsVector();
+  if (coords->result_type()->Is<ast::type::VectorType>()) {
+    auto* vec = coords->result_type()->As<ast::type::VectorType>();
     packed_size = vec->size() + 1;
     packed_el_ty = vec->type();
   } else {
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 974b56d..0b77675 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -881,7 +881,7 @@
     return true;
   }
 
-  if (!data_type->IsVector()) {
+  if (!data_type->Is<ast::type::VectorType>()) {
     error_ = "Member accessor without a struct or vector. Something is wrong";
     return false;
   }
@@ -1191,7 +1191,8 @@
       return false;
     }
 
-    if (result_type->IsVector() && !e->AsConstructor()->IsScalarConstructor()) {
+    if (result_type->Is<ast::type::VectorType>() &&
+        !e->AsConstructor()->IsScalarConstructor()) {
       return false;
     }
 
@@ -1202,8 +1203,8 @@
 
     auto* sc = e->AsConstructor()->AsScalarConstructor();
     ast::type::Type* subtype = result_type->UnwrapAll();
-    if (subtype->IsVector()) {
-      subtype = subtype->AsVector()->type()->UnwrapAll();
+    if (subtype->Is<ast::type::VectorType>()) {
+      subtype = subtype->As<ast::type::VectorType>()->type()->UnwrapAll();
     } else if (subtype->Is<ast::type::MatrixType>()) {
       subtype = subtype->As<ast::type::MatrixType>()->type()->UnwrapAll();
     } else if (subtype->Is<ast::type::ArrayType>()) {
@@ -1244,12 +1245,14 @@
 
   bool can_cast_or_copy = result_type->is_scalar();
 
-  if (result_type->IsVector() && result_type->AsVector()->type()->is_scalar()) {
+  if (result_type->Is<ast::type::VectorType>() &&
+      result_type->As<ast::type::VectorType>()->type()->is_scalar()) {
     auto* value_type = values[0]->result_type()->UnwrapAll();
     can_cast_or_copy =
-        (value_type->IsVector() &&
-         value_type->AsVector()->type()->is_scalar() &&
-         result_type->AsVector()->size() == value_type->AsVector()->size());
+        (value_type->Is<ast::type::VectorType>() &&
+         value_type->As<ast::type::VectorType>()->type()->is_scalar() &&
+         result_type->As<ast::type::VectorType>()->size() ==
+             value_type->As<ast::type::VectorType>()->size());
   }
   if (can_cast_or_copy) {
     return GenerateCastOrCopyOrPassthrough(result_type, values[0]);
@@ -1263,8 +1266,8 @@
   bool result_is_constant_composite = constructor_is_const;
   bool result_is_spec_composite = false;
 
-  if (result_type->IsVector()) {
-    result_type = result_type->AsVector()->type();
+  if (result_type->Is<ast::type::VectorType>()) {
+    result_type = result_type->As<ast::type::VectorType>()->type();
   }
 
   OperandList ops;
@@ -1312,8 +1315,8 @@
     //
     // For cases 1 and 2, if the type is different we also may need to insert
     // a type cast.
-    if (value_type->IsVector()) {
-      auto* vec = value_type->AsVector();
+    if (value_type->Is<ast::type::VectorType>()) {
+      auto* vec = value_type->As<ast::type::VectorType>();
       auto* vec_type = vec->type();
 
       auto value_type_id = GenerateTypeIfNeeded(vec_type);
@@ -1426,7 +1429,8 @@
               to_type->Is<ast::type::I32Type>()) ||
              (from_type->Is<ast::type::F32Type>() &&
               to_type->Is<ast::type::F32Type>()) ||
-             (from_type->IsVector() && (from_type == to_type))) {
+             (from_type->Is<ast::type::VectorType>() &&
+              (from_type == to_type))) {
     return val_id;
   } else if ((from_type->Is<ast::type::I32Type>() &&
               to_type->Is<ast::type::U32Type>()) ||
@@ -2454,8 +2458,8 @@
     }
   } else if (type->Is<ast::type::U32Type>()) {
     push_type(spv::Op::OpTypeInt, {result, Operand::Int(32), Operand::Int(0)});
-  } else if (type->IsVector()) {
-    if (!GenerateVectorType(type->AsVector(), result)) {
+  } else if (type->Is<ast::type::VectorType>()) {
+    if (!GenerateVectorType(type->As<ast::type::VectorType>(), result)) {
       return 0;
     }
   } else if (type->IsVoid()) {
diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h
index ffda68c..f523b71 100644
--- a/src/writer/spirv/builder.h
+++ b/src/writer/spirv/builder.h
@@ -33,6 +33,7 @@
 #include "src/ast/type/pointer_type.h"
 #include "src/ast/type/storage_texture_type.h"
 #include "src/ast/type/struct_type.h"
+#include "src/ast/type/vector_type.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/context.h"
 #include "src/scope_stack.h"
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index 53e2690..9411aa5 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -547,8 +547,8 @@
 
   } else if (type->Is<ast::type::U32Type>()) {
     out_ << "u32";
-  } else if (type->IsVector()) {
-    auto* vec = type->AsVector();
+  } else if (type->Is<ast::type::VectorType>()) {
+    auto* vec = type->As<ast::type::VectorType>();
     out_ << "vec" << vec->size() << "<";
     if (!EmitType(vec->type())) {
       return false;