Repository: vue-gl/vue-gl
Pull request #773 (2019-12-22 12:45:20)

Prop validations
* `number` prop into `int` and `float`
* Set custom prop validators
* Set some props to be required


Patch:
diff --git a/docs/index.md b/docs/README.md
similarity index 91%
rename from docs/index.md
rename to docs/README.md
index a59c2f6..e75fe4b 100644
--- a/docs/index.md
+++ b/docs/README.md
@@ -4,16 +4,20 @@ nav_order: 1
 # Introduction
 {: .no_toc}
 
-1. Table of contents
+---
+
+## Table of contents
+{: .text-delta .no_toc}
+
+* toc
 {:toc}
 
 ## Overview
-
 [Vue.js](https://vuejs.org) components for reactive 3D rendering. Depends on [three.js](https://threejs.org/).
 
-You can render 3D components on canvas by coding custom html tags.
-It's not only for integration with other Vue.js applications,
-but also for drawing 3D graphics more easier!
+You can render 3D components on canvas by coding custom html tags. It's useful not
+only for integration with other Vue.js applications, but also for drawing 3D graphics
+more easier!
 
 ## Getting started
 
diff --git a/docs/prop-types.md b/docs/prop-types.md
new file mode 100644
index 0000000..b68a755
--- /dev/null
+++ b/docs/prop-types.md
@@ -0,0 +1,242 @@
+---
+nav_order: 2
+---
+# Prop types
+{: .no_toc}
+
+---
+
+## Table of contents
+{: .text-delta .no_toc}
+
+* toc
+{:toc}
+
+## Overview
+VueGL components recognize a prop value as its prop type. Therefore you don't need
+to bind raw objects or primitives even still you can do that.
+
+Each prop type has a specific method to parse prop values. For example, an `int`
+type prop is parsed by `parseInt()` function internally. So any values castable to
+string and parsable as integer are acceptable.
+
+Examples below set the `segments` prop to `16`.
+
+* Passing a static string
+
+  ```html
+  <vgl-circle-geometry segments="16" />
+  ```
+
+* Passing a number
+
+  ```html
+  <vgl-circle-geometry :segments="16" />
+  ```
+
+## List of prop types
+
+### ***boolean***
+`true` or `false`. When prop value is static, presence of the prop name sets the
+prop value to `true`. Default value is always `false`. When you bind the prop to
+javascript expression, prop value should be a boolean not a truthy or falsy values.
+
+Examples below set the `antialias` prop to `true`.
+
+```html
+<vgl-renderer antialias />
+```
+
+```html
+<vgl-renderer :antialias="true" />
+```
+
+### ***int***
+Integer number. It can be a premitive or an object that is castable to string because
+prop is parsed by `parseInt()` function.
+
+Examples below set the `radial-segments` prop to `12`.
+
+```html
+<vgl-cylinder-geometry radial-segments="12" />
+```
+
+```html
+<vgl-cylinder-geometry :radial-segments="12" />
+```
+
+### ***float***
+Float number. It can be a premitive or an object that is castable to string because
+prop is parsed by `parseFloat()` function.
+
+Examples below set the `fov` prop to `63.35`.
+
+```html
+<vgl-perspective-camera fov="63.35" />
+```
+
+```html
+<vgl-perspective-camera :fov="63.35" />
+```
+
+### ***string***
+Any string.
+
+### ***name***
+Identifier string without space charactor. Used for object specification in VueGL's
+namespace.
+
+### ***names***
+Either space separated name strings or an array of name strings. Used for multiple
+object specification in VueGL's namespace.
+
+Examples below set materials named `mat1` and `mat2` to the mesh object.
+
+```html
+<vgl-mesh material="mat1 mat2" />
+```
+
+```html
+<vgl-mesh :material="['mat1', 'mat2']" />
+```
+
+### ***color***
+Either a CSS style color string, a hexadecimal value or a `THREE.Color` instance.
+The prop value is passed to `THREE.Color()` constructor.
+
+Examples below set the light color to `0x4ef3a7`.
+
+```html
+<vgl-ambient-light color="#4ef3a7" />
+```
+
+```html
+<vgl-ambient-light color="rgb(78, 243, 167)" />
+```
+
+```html
+<vgl-ambient-light :color="'#4ef3a7'" />
+```
+
+```html
+<vgl-ambient-light :color="0x4ef3a7" />
+```
+
+```html
+<vgl-ambient-light :color="new THREE.Color(0x4ef3a7)" />
+```
+
+### ***vector2***
+Either a string that represents space separated 2 coodinates or a `THREE.Vector2`
+instance.
+
+Examples below set the `offset` prop to `(x, y) = (12.34, 56.78)`.
+
+```html
+<vgl-texture offset="12.34 56.78" />
+```
+
+```html
+<vgl-texture :offset="new THREE.Vector2(12.34, 56.78)">
+```
+
+### ***vector3***
+Either a string that represents space separated 3 coodinates or a `THREE.Vector3`
+instance.
+
+Examples below set the `position` prop to `(x, y, z) = (1.23, 3.45, 4.56)`.
+
+```html
+<vgl-group position="1.23 3.45 4.56" />
+```
+
+```html
+<vgl-group :position="new THREE.Vector3(1.23, 3.45, 4.56)" />
+```
+
+### ***euler***
+Either a string that represents space separated 3 coodinates and order string or
+a `THREE.Euler` instance.
+
+Examples below set the `rotation` prop to
+`(x, y, z, order) = (0.12, 0.23, 0.34, 'ZYX')`.
+
+```html
+<vgl-group rotation="0.12 0.23 0.34 ZYX" />
+```
+
+```html
+<vgl-group :rotation="new THREE.Euler(0.12, 0.23, 0.34, 'ZYX')" />
+```
+
+### ***quaternion***
+Either a string that represents space separated 4 coodinates or a `THREE.Quaternion`
+instance.
+
+Examples below set the `rotationQuaternion` prop to
+`(x, y, z, w) = (0.91, 0.23, 0.34, 0.88)`.
+
+```html
+<vgl-group rotation-quaternion="0.91 0.23 0.34 0.88" />
+```
+
+```html
+<vgl-group :rotation-quaternion="new THREE.Quaternion(0.91, 0.23, 0.34, 0.88)" />
+```
+
+### ***spherical***
+Either a string that represents space separated 3 coodinates or a `THREE.Spherical`
+instance.
+
+Examples below set the `orbit-position` prop to
+`(radius, phi, theta) = (123.4, 0.23, 0.34)`.
+
+```html
+<vgl-perspective-camera orbit-position="123.4 0.23 0.34" />
+```
+
+```html
+<vgl-perspective-camera :orbit-position="new THREE.Spherical(123.4, 0.23, 0.34)" />
+```
+
+### ***floatArray***
+Either a string that contains comma separated number strings or an array of values
+those are castable to float numbers. Each value is parsed by `parseFloat()` function.
+
+Examples below set the `position-attribute` prop to `[1.1, 1.2, 1.3, 3.1, 3.2, 3.3]`.
+
+```html
+<vgl-geometry position-attribute="1.1, 1.2, 1.3, 3.1, 3.2, 3.3" />
+```
+
+```html
+<vgl-geometry :position-attribute="['1.1', '1.2', '1.3', '3.1', '3.2', '3.3']" />
+```
+
+```html
+<vgl-geometry :position-attribute="[1.1, 1.2, 1.3, 3.1, 3.2, 3.3]" />
+```
+
+### ***vector2Array***
+Either a string or an array. The string is splited by comma delimeters first, and
+each part of the string is parsed as space separated 2 coodinates of 2D vector. If
+the value is an array, each item of the array can be either a string or a `THREE.Vector2`
+instance.
+
+Examples below set the `points` prop to
+`[new THREE.Vector2(-1.2, 0), new THREE.Vector2(1, 2.5)]`.
+
+```html
+<vgl-lathe-geometry points="-1.2 0, 1 2.5" />
+```
+
+```html
+<vgl-lathe-geometry :points="['-1.2 0', '1 2.5']" />
+```
+
+```html
+<vgl-lathe-geometry :points="[new THREE.Vector2(-1.2, 0), new THREE.Vector2(1, 2.5)]" />
+```
+
+### ***fog***
+Space-separated paramaters as color, near and far, corresponding [THREE.Fog](https://threejs.org/docs/#api/en/scenes/Fog)
diff --git a/docs/property-types.md b/docs/property-types.md
deleted file mode 100644
index bcd6c43..0000000
--- a/docs/property-types.md
+++ /dev/null
@@ -1,77 +0,0 @@
----
-nav_order: 2
----
-# Property types
-{: .no_toc}
-
-1. Table of contents
-{:toc}
-
-## Overview
-
-Any properties of all components accept both strings and raw datas (primitives
-or objects). If the property is a string, it will be parsed as a suitable data
-type. Otherwise, the property data is used as a raw data type.
-
-For example,
-
-```html
-<vgl-renderer>
-  <vgl-scene>
-    <vgl-axis-helper position="1 1.5 3"></vgl-axis-helper>
-  </vgl-scene>
-  <vgl-perspective-camera orbitPosition="3 1 1"></vgl-perspective-camera>
-</vgl-renderer>
-```
-
-This will show an [axis helper](vgl-axis-helper) at the position (x=1, y=1.5,
-z=3), with a [perspective camera](vgl-perspective-camera) at (r=3, phi=1,
-theta=1). The type of the `position` property of [VglObject3d](vgl-object-3d)
-is vector3, so that it is parsed as a
-[THREE.Vector3](https://threejs.org/docs/index.html#api/math/Vector3) object.
-The type of the `orbitPosition` property is spherical, so that it is parsed as
-a [THREE.Spherical](https://threejs.org/docs/index.html#api/math/Spherical) object.
-
-If you would like to pass raw datas (will skip parsing and may speed up your
-app), use data binding directive.
-
-```html
-<vgl-renderer>
-  <vgl-scene>
-    <vgl-axis-helper :position="new THREE.Vector3(1, 1.5, 3)"></vgl-axis-helper>
-  </vgl-scene>
-  <vgl-perspective-camera :orbitPosition="new THREE.Spherical(3, 1, 1)"></vgl-perspective-camera>
-</vgl-renderer>
-```
-
-## Types
-
-Following list shows all property types and parsing schemas.
-
-- ***boolean***  
-  Whether attribute exists or not.
-- ***euler***  
-  Space-separated 3 numbers and 1 string are parsed as x, y, z, order, corresponding
-  [THREE.Euler](https://threejs.org/docs/index.html#api/math/Euler).
-- ***float***  
-  Parsed as a float number using `parseFloat()`.
-- ***int***  
-  Parsed as an integer number using `parseInt()`.
-- ***spherical***  
-  Space-separated 3 numbers are parsed as radius, phi, theta, corresponding [THREE.Spherical](https://threejs.org/docs/index.html#api/math/Spherical).
-- ***string***  
-  Always pass through.
-- ***vector2***  
-  Space-separated 2 numbers are parsed as x, y, corresponding [THREE.Vector2](https://threejs.org/docs/index.html#api/math/Vector2).
-- ***vector3***  
-  Space-separated 3 numbers are parsed as x, y, z, corresponding [THREE.Vector3](https://threejs.org/docs/index.html#api/math/Vector3).
-- ***floatArray***
-  Parsed as an array of float numbers.
-- ***vector2Array***
-  Parsed as an array of vector2s.
-- ***fog***
-  Space-separated paramaters as color, near and far, corresponding [THREE.Fog](https://threejs.org/docs/#api/en/scenes/Fog)
-- ***name***
-  A string representing the component name. It must not contain any spaces.
-- ***names***
-  Space separated strings or an array of string.
diff --git a/markdownlint.config.yml b/markdownlint.config.yml
index 18fbe34..aa0d0f8 100644
--- a/markdownlint.config.yml
+++ b/markdownlint.config.yml
@@ -1,2 +1,4 @@
+MD013:
+  code_blocks: false
 MD022:
   lines_below: 0
diff --git a/src/cameras/vgl-camera.js b/src/cameras/vgl-camera.js
index b7df22e..c1d0ee3 100644
--- a/src/cameras/vgl-camera.js
+++ b/src/cameras/vgl-camera.js
@@ -1,7 +1,8 @@
 import { Camera, Vector3 } from 'three';
 import VglObject3d from '../core/vgl-object3d';
 import { parseVector3, parseSpherical } from '../parsers';
-import { vector3, spherical } from '../types';
+import { vector3, spherical, name } from '../types';
+import { validateVector3, validateSpherical, validateName } from '../validators';
 
 /**
  * This is abstract base component for cameras,
@@ -20,13 +21,15 @@ export default {
      * Position in 3D space for the camera to point towards.
      * This property overwrite rotation property when both defined.
      */
-    orbitTarget: vector3,
+    orbitTarget: { type: vector3, validator: validateVector3 },
     /**
      * Spherical position around orbitTarget.
      * This property overwrite position and rotation properties.
      * If orbitTarget is not defined, automatically set to (0, 0, 0).
      */
-    orbitPosition: spherical,
+    orbitPosition: { type: spherical, validator: validateSpherical },
+    /** Name of the camera */
+    name: { type: name, required: true, validator: validateName },
   },
   computed: {
     /** The THREE.Camera instance. */
@@ -59,9 +62,9 @@ export default {
       },
       immediate: true,
     },
-    name(name, oldName) {
+    name(newName, oldName) {
       this.vglNamespace.cameras.delete(oldName, this.inst);
-      this.vglNamespace.cameras.set(name, this.inst);
+      this.vglNamespace.cameras.set(newName, this.inst);
     },
     orbitTarget(orbitTarget) {
       const target = parseVector3(orbitTarget);
diff --git a/src/cameras/vgl-orthographic-camera.js b/src/cameras/vgl-orthographic-camera.js
index 09d8897..7a0ef53 100644
--- a/src/cameras/vgl-orthographic-camera.js
+++ b/src/cameras/vgl-orthographic-camera.js
@@ -1,6 +1,6 @@
 import { OrthographicCamera } from 'three';
 import VglCamera from './vgl-camera';
-import { number } from '../types';
+import { float } from '../types';
 
 /**
  * Camera that uses orthographic projection,
@@ -14,11 +14,11 @@ export default {
   mixins: [VglCamera],
   props: {
     /** Zoom factor of the camera. */
-    zoom: { type: number, default: 1 },
+    zoom: { type: float, default: 1 },
     /** Camera frustum near plane. */
-    near: { type: number, default: 0.1 },
+    near: { type: float, default: 0.1 },
     /** Camera frustum far plane. */
-    far: { type: number, default: 2000 },
+    far: { type: float, default: 2000 },
   },
   computed: {
     /** The THREE.OrthographicCamera instance. */
diff --git a/src/cameras/vgl-perspective-camera.js b/src/cameras/vgl-perspective-camera.js
index 9197c79..fb0c477 100644
--- a/src/cameras/vgl-perspective-camera.js
+++ b/src/cameras/vgl-perspective-camera.js
@@ -1,6 +1,6 @@
 import { PerspectiveCamera } from 'three';
 import VglCamera from './vgl-camera';
-import { number } from '../types';
+import { float } from '../types';
 
 /**
  * Camera that uses perspective projection,
@@ -14,13 +14,13 @@ export default {
   mixins: [VglCamera],
   props: {
     /** Zoom factor of the camera. */
-    zoom: { type: number, default: 1 },
+    zoom: { type: float, default: 1 },
     /** Camera frustum near plane. */
-    near: { type: number, default: 0.1 },
+    near: { type: float, default: 0.1 },
     /** Camera frustum far plane. */
-    far: { type: number, default: 2000 },
+    far: { type: float, default: 2000 },
     /** Camera frustum vertical field of view, from bottom to top of view, in degrees. */
-    fov: { type: number, default: 50 },
+    fov: { type: float, default: 50 },
   },
   computed: {
     /** The THREE.PerspectiveCamera instance. */
diff --git a/src/core/vgl-geometry.js b/src/core/vgl-geometry.js
index f7f2589..7da0710 100644
--- a/src/core/vgl-geometry.js
+++ b/src/core/vgl-geometry.js
@@ -1,6 +1,6 @@
 import { BufferGeometry, BufferAttribute } from 'three';
 import { name, floatArray } from '../types';
-import { nameValidator } from '../validators';
+import { validateName, validateFloatArray } from '../validators';
 import { parseArray } from '../parsers';
 
 /**
@@ -17,13 +17,13 @@ export default {
   },
   props: {
     /** Name of the component. */
-    name: { type: name, validator: nameValidator },
+    name: { type: name, required: true, validator: validateName },
     /** The x, y, and z coordinates of each vertex in this geometry. */
-    positionAttribute: floatArray,
+    positionAttribute: { type: floatArray, validator: validateFloatArray },
     /** The red, green, and blue channels of vertex color of each vertex in this geometry. */
-    colorAttribute: floatArray,
+    colorAttribute: { type: floatArray, validator: validateFloatArray },
     /** The x, y, and z components of the vertex normal vector of each vertex in this geometry. */
-    normalAttribute: floatArray,
+    normalAttribute: { type: floatArray, validator: validateFloatArray },
   },
   computed: {
     /** The THREE.BufferGeometry instance. */
diff --git a/src/core/vgl-object3d.js b/src/core/vgl-object3d.js
index d8141dd..f8b4110 100644
--- a/src/core/vgl-object3d.js
+++ b/src/core/vgl-object3d.js
@@ -2,13 +2,11 @@ import { Object3D } from 'three';
 import Tree from './tree';
 import { parseVector3, parseEuler, parseQuaternion } from '../parsers';
 import {
-  vector3,
-  euler,
-  quaternion,
-  boolean,
-  name,
+  vector3, euler, quaternion, boolean, name,
 } from '../types';
-import { nameValidator } from '../validators';
+import {
+  validateName, validateVector3, validateEuler, validateQuaternion,
+} from '../validators';
 
 /**
  * This is the base mixin component for most object components in VueGL,
@@ -22,23 +20,23 @@ import { nameValidator } from '../validators';
 export default {
   props: {
     /** The object's local position as a 3D vector. */
-    position: vector3,
+    position: { type: vector3, validator: validateVector3 },
     /** The object's local rotation as a euler angle. */
-    rotation: euler,
+    rotation: { type: euler, validator: validateEuler },
     /**
      * The object's local rotation as a quaternion (specified in x, y, z, w order).
      * Do not use in conjunction with the rotation prop, since they both control the same property
      * of the underlying THREE.Object3D object.
      */
-    rotationQuaternion: quaternion,
+    rotationQuaternion: { type: quaternion, validator: validateQuaternion },
     /** The object's local scale as a 3D vector. */
-    scale: vector3,
+    scale: { type: vector3, validator: validateVector3 },
     /** Whether the object gets rendered into shadow map. */
     castShadow: boolean,
     /** Whether the material receives shadows. */
     receiveShadow: boolean,
     /** Optional name of the object. */
-    name: { type: name, validator: nameValidator },
+    name: { type: name, validator: validateName },
     /** Whether the object is visible. */
     hidden: boolean,
   },
diff --git a/src/extras/vgl-curve.js b/src/extras/vgl-curve.js
index e273ecf..3b484d9 100644
--- a/src/extras/vgl-curve.js
+++ b/src/extras/vgl-curve.js
@@ -1,6 +1,6 @@
 import { Curve } from 'three';
 import { name } from '../types';
-import { nameValidator } from '../validators';
+import { validateName } from '../validators';
 
 /**
  * An abstract base component for representing a curve, corresponding
@@ -14,7 +14,7 @@ export default {
   },
   props: {
     /** Name of the component. */
-    name: { type: name, validator: nameValidator },
+    name: { type: name, required: true, validator: validateName },
   },
   computed: {
     /** The THREE.Curve instance. */
diff --git a/src/extras/vgl-path.js b/src/extras/vgl-path.js
index c0cb10a..a74a88a 100644
--- a/src/extras/vgl-path.js
+++ b/src/extras/vgl-path.js
@@ -2,6 +2,7 @@ import { Path } from 'three';
 import VglCurvePath from './vgl-curve-path';
 import { vector2Array } from '../types';
 import { parseVector2Array } from '../parsers';
+import { validateVector2Array } from '../validators';
 
 /**
  * A 2D path representation, Corresponding
@@ -14,7 +15,7 @@ export default {
   mixins: [VglCurvePath],
   props: {
     /** The array of points as a LineCurve. */
-    path: vector2Array,
+    path: { type: vector2Array, validator: validateVector2Array },
   },
   computed: {
     /** The THREE.Path instance. */
diff --git a/src/geometries/vgl-box-geometry.js b/src/geometries/vgl-box-geometry.js
index c8fd600..8235014 100644
--- a/src/geometries/vgl-box-geometry.js
+++ b/src/geometries/vgl-box-geometry.js
@@ -1,6 +1,6 @@
 import { BoxBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
-import { number } from '../types';
+import { float, int } from '../types';
 
 /**
  * This is the quadrilateral primitive geometry component,
@@ -13,17 +13,17 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Width of the sides on the X axis. */
-    width: { type: number, default: 1 },
+    width: { type: float, default: 1 },
     /** Height of the sides on the Y axis. */
-    height: { type: number, default: 1 },
+    height: { type: float, default: 1 },
     /** Depth of the sides on the Z axis. */
-    depth: { type: number, default: 1 },
+    depth: { type: float, default: 1 },
     /** Number of segmented faces along the width of the sides. */
-    widthSegments: { type: number, default: 1 },
+    widthSegments: { type: int, default: 1 },
     /** Number of segmented faces along the height of the sides. */
-    heightSegments: { type: number, default: 1 },
+    heightSegments: { type: int, default: 1 },
     /** Number of segmented faces along the depth of the sides. */
-    depthSegments: { type: number, default: 1 },
+    depthSegments: { type: int, default: 1 },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-circle-geometry.js b/src/geometries/vgl-circle-geometry.js
index d3a101e..2d540c6 100644
--- a/src/geometries/vgl-circle-geometry.js
+++ b/src/geometries/vgl-circle-geometry.js
@@ -1,6 +1,6 @@
 import { CircleBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
-import { number } from '../types';
+import { float, int } from '../types';
 
 /**
  * This is a simple shape component of Euclidean geometry,
@@ -18,13 +18,13 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Radius of the circle. */
-    radius: { type: number, default: 1 },
+    radius: { type: float, default: 1 },
     /** Number of segments (triangles). */
-    segments: { type: number, default: 8 },
+    segments: { type: int, default: 8 },
     /** Start angle for first segment. */
-    thetaStart: { type: number, default: 0 },
+    thetaStart: { type: float, default: 0 },
     /** The central angle of the circular sector. */
-    thetaLength: { type: number, default: Math.PI * 2 },
+    thetaLength: { type: float, default: Math.PI * 2 },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-cone-geometry.js b/src/geometries/vgl-cone-geometry.js
index 04976b6..97924f2 100644
--- a/src/geometries/vgl-cone-geometry.js
+++ b/src/geometries/vgl-cone-geometry.js
@@ -1,6 +1,6 @@
 import { ConeBufferGeometry } from 'three';
 import VglCylinderGeometry from './vgl-cylinder-geometry';
-import { number } from '../types';
+import { float } from '../types';
 
 /**
  * This is a component for generating cone geometries,
@@ -13,7 +13,7 @@ export default {
   mixins: [VglCylinderGeometry],
   props: {
     /** Radius of the cone at the base. */
-    radius: { type: number, default: 1 },
+    radius: { type: float, default: 1 },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-cylinder-geometry.js b/src/geometries/vgl-cylinder-geometry.js
index b995f8d..4966ee7 100644
--- a/src/geometries/vgl-cylinder-geometry.js
+++ b/src/geometries/vgl-cylinder-geometry.js
@@ -1,6 +1,6 @@
 import { CylinderBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
-import { number, boolean } from '../types';
+import { float, int, boolean } from '../types';
 
 /**
  * This is a component for generating cylinder geometries,
@@ -13,21 +13,21 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Radius of the cylinder at the top. */
-    radiusTop: { type: number, default: 1 },
+    radiusTop: { type: float, default: 1 },
     /** Radius of the cylinder at the bottom. */
-    radiusBottom: { type: number, default: 1 },
+    radiusBottom: { type: float, default: 1 },
     /** Height of the cylinder. */
-    height: { type: number, default: 1 },
+    height: { type: float, default: 1 },
     /** Number of segmented faces around the circumference of the cylinder. */
-    radialSegments: { type: number, default: 8 },
+    radialSegments: { type: int, default: 8 },
     /** Number of rows of faces along the height of the cylinder. */
-    heightSegments: { type: number, default: 1 },
+    heightSegments: { type: int, default: 1 },
     /** A Boolean indicating whether the ends of the cylinder are open or capped. */
     openEnded: boolean,
     /** Start angle for first segment. */
-    thetaStart: { type: number, default: 0 },
+    thetaStart: { type: float, default: 0 },
     /** The central angle of the circular sector. */
-    thetaLength: { type: number, default: Math.PI * 2 },
+    thetaLength: { type: float, default: Math.PI * 2 },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-dodecahedron-geometry.js b/src/geometries/vgl-dodecahedron-geometry.js
index 3a7b361..11c3cce 100644
--- a/src/geometries/vgl-dodecahedron-geometry.js
+++ b/src/geometries/vgl-dodecahedron-geometry.js
@@ -1,6 +1,6 @@
 import { DodecahedronBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
-import { number } from '../types';
+import { float, int } from '../types';
 
 /**
  * A component for generating a dodecahedron geometries,
@@ -13,9 +13,9 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Radius of the dodecahedron. */
-    radius: { type: number, default: 1 },
+    radius: { type: float, default: 1 },
     /** Setting this to a value greater than 0 adds vertices making it no longer a dodecahedron. */
-    detail: { type: number, default: 0 },
+    detail: { type: int, default: 0 },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-extrude-geometry.js b/src/geometries/vgl-extrude-geometry.js
index 50ad0ee..c894724 100644
--- a/src/geometries/vgl-extrude-geometry.js
+++ b/src/geometries/vgl-extrude-geometry.js
@@ -1,8 +1,10 @@
 import { ExtrudeBufferGeometry } from 'three';
-import { boolean, number, names } from '../types';
+import {
+  boolean, float, int, names,
+} from '../types';
 import VglGeometry from '../core/vgl-geometry';
 import { parseNames } from '../parsers';
-import { namesValidator } from '../validators';
+import { validateNames } from '../validators';
 
 /**
  * A component for creating extruded geometry from a path shape,
@@ -15,25 +17,25 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** The Shape names */
-    shapes: { type: names, validator: namesValidator },
+    shapes: { type: names, validator: validateNames },
     /** int. Number of points on the curves */
-    curveSegments: number,
+    curveSegments: int,
     /** int. Number of points used for subdividing segments
      * along the depth of the extruded spline
      */
-    steps: number,
+    steps: int,
     /** float. Depth to extrude the shape */
-    depth: number,
+    depth: float,
     /** Apply beveling to the shape */
     bevelEnabled: boolean,
     /** float. How deep into the original shape the bevel goes */
-    bevelThickness: number,
+    bevelThickness: float,
     /** float. Distance from the shape outline that the bevel extends */
-    bevelSize: number,
+    bevelSize: float,
     /** float. Distance from the shape outline that the bevel starts */
-    bevelOffset: number,
+    bevelOffset: float,
     /** int. Number of bevel layers */
-    bevelSegments: number,
+    bevelSegments: int,
     /** THREE.Curve. A 3D spline path along which the shape should be extruded */
     extrudePath: Object,
     /**  Object that provides UV generator functions */
diff --git a/src/geometries/vgl-icosahedron-geometry.js b/src/geometries/vgl-icosahedron-geometry.js
index f3aebd3..4dcc3a3 100644
--- a/src/geometries/vgl-icosahedron-geometry.js
+++ b/src/geometries/vgl-icosahedron-geometry.js
@@ -1,6 +1,6 @@
 import { IcosahedronBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
-import { number } from '../types';
+import { float, int } from '../types';
 
 /**
  * A component for generating a icosahedron geometries,
@@ -13,9 +13,9 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Radius of the icosahedron. */
-    radius: { type: number, default: 1 },
+    radius: { type: float, default: 1 },
     /** Setting this to a value greater than 0 adds vertices making it no longer a icosahedron. */
-    detail: { type: number, default: 0 },
+    detail: { type: int, default: 0 },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-lathe-geometry.js b/src/geometries/vgl-lathe-geometry.js
index b341d1a..676ee38 100644
--- a/src/geometries/vgl-lathe-geometry.js
+++ b/src/geometries/vgl-lathe-geometry.js
@@ -1,7 +1,8 @@
 import { LatheBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
 import { parseVector2Array } from '../parsers';
-import { vector2Array, number } from '../types';
+import { vector2Array, float, int } from '../types';
+import { validateVector2Array } from '../validators';
 
 /**
  * A component for creating extruded geometry from a path shape,
@@ -14,13 +15,13 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Array of Vector2s. The x-coordinate of each point must be greater than zero. */
-    points: { type: vector2Array, required: true },
+    points: { type: vector2Array, required: true, validator: validateVector2Array },
     /** The number of circumference segments to generate. */
-    segments: { type: number, default: 12 },
+    segments: { type: int, default: 12 },
     /** The starting angle in radians. */
-    phiStart: { type: number, default: 0 },
+    phiStart: { type: float, default: 0 },
     /** The radian (0 to 2PI) range of the lathed section. */
-    phiLength: { type: number, default: Math.PI * 2 },
+    phiLength: { type: float, default: Math.PI * 2 },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-octahedron-geometry.js b/src/geometries/vgl-octahedron-geometry.js
index 79f0a76..f5165ae 100644
--- a/src/geometries/vgl-octahedron-geometry.js
+++ b/src/geometries/vgl-octahedron-geometry.js
@@ -1,6 +1,6 @@
 import { OctahedronBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
-import { number } from '../types';
+import { float, int } from '../types';
 
 /**
  * A component for generating a octahedron geometries,
@@ -13,9 +13,9 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Radius of the octahedron. */
-    radius: { type: number, default: 1 },
+    radius: { type: float, default: 1 },
     /** Setting this to a value greater than 0 adds vertices making it no longer a octahedron. */
-    detail: { type: number, default: 0 },
+    detail: { type: int, default: 0 },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-plane-geometry.js b/src/geometries/vgl-plane-geometry.js
index b25c05d..997cc2f 100644
--- a/src/geometries/vgl-plane-geometry.js
+++ b/src/geometries/vgl-plane-geometry.js
@@ -1,6 +1,6 @@
 import { PlaneBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
-import { number } from '../types';
+import { float, int } from '../types';
 
 /**
  * A component for generating plane geometries,
@@ -13,13 +13,13 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Width along the X axis. */
-    width: { type: number, default: 1 },
+    width: { type: float, default: 1 },
     /** Height along the Y axis. */
-    height: { type: number, default: 1 },
+    height: { type: float, default: 1 },
     /** Number of segments along the X axis. */
-    widthSegments: { type: number, default: 1 },
+    widthSegments: { type: int, default: 1 },
     /** Number of segments along the Y axis. */
-    heightSegments: { type: number, default: 1 },
+    heightSegments: { type: int, default: 1 },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-ring-geometry.js b/src/geometries/vgl-ring-geometry.js
index 19fbef8..6d0c5f7 100644
--- a/src/geometries/vgl-ring-geometry.js
+++ b/src/geometries/vgl-ring-geometry.js
@@ -1,6 +1,6 @@
 import { RingBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
-import { number } from '../types';
+import { float, int } from '../types';
 
 /**
  * This is a simple shape component of Euclidean geometry,
@@ -18,17 +18,17 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Inner radius of the ring. */
-    innerRadius: { type: number, default: 0.5 },
+    innerRadius: { type: float, default: 0.5 },
     /** Outer radius of the ring. */
-    outerRadius: { type: number, default: 1 },
+    outerRadius: { type: float, default: 1 },
     /** Number of segments along to the tangential direction. */
-    thetaSegments: { type: number, default: 8 },
+    thetaSegments: { type: int, default: 8 },
     /** Number of segments along to the radial direction. */
-    phiSegments: { type: number, default: 1 },
+    phiSegments: { type: int, default: 1 },
     /** The starting angle. */
-    thetaStart: { type: number, default: 0 },
+    thetaStart: { type: float, default: 0 },
     /** The central angle. */
-    thetaLength: { type: number, default: Math.PI * 2 },
+    thetaLength: { type: float, default: Math.PI * 2 },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-sphere-geometry.js b/src/geometries/vgl-sphere-geometry.js
index 7a5695d..1406df5 100644
--- a/src/geometries/vgl-sphere-geometry.js
+++ b/src/geometries/vgl-sphere-geometry.js
@@ -1,6 +1,6 @@
 import { SphereBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
-import { number } from '../types';
+import { float, int } from '../types';
 
 /**
  * This is a component for generating sphere geometries,
@@ -13,19 +13,19 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Sphere radius. */
-    radius: { type: number, default: 1 },
+    radius: { type: float, default: 1 },
     /** Number of horizontal segments. */
-    widthSegments: { type: number, default: 8 },
+    widthSegments: { type: int, default: 8 },
     /** Number of vertical segments. */
-    heightSegments: { type: number, default: 6 },
+    heightSegments: { type: int, default: 6 },
     /** Specify horizontal starting angle. */
-    phiStart: { type: number, default: 0 },
+    phiStart: { type: float, default: 0 },
     /** Specify horizontal sweep angle size. */
-    phiLength: { type: number, default: Math.PI * 2 },
+    phiLength: { type: float, default: Math.PI * 2 },
     /** Specify vertical starting angle. */
-    thetaStart: { type: number, default: 0 },
+    thetaStart: { type: float, default: 0 },
     /** Specify vertical sweep angle size. */
-    thetaLength: { type: number, default: Math.PI },
+    thetaLength: { type: float, default: Math.PI },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-tetrahedron-geometry.js b/src/geometries/vgl-tetrahedron-geometry.js
index 5878d15..2aa3210 100644
--- a/src/geometries/vgl-tetrahedron-geometry.js
+++ b/src/geometries/vgl-tetrahedron-geometry.js
@@ -1,6 +1,6 @@
 import { TetrahedronBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
-import { number } from '../types';
+import { float, int } from '../types';
 
 /**
  * A component for generating a tetrahedron geometries,
@@ -13,9 +13,9 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Radius of the tetrahedron. */
-    radius: { type: number, default: 1 },
+    radius: { type: float, default: 1 },
     /** Setting this to a value greater than 0 adds vertices making it no longer a tetrahedron. */
-    detail: { type: number, default: 0 },
+    detail: { type: int, default: 0 },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-text-geometry.js b/src/geometries/vgl-text-geometry.js
index ed1e67f..6a795e4 100644
--- a/src/geometries/vgl-text-geometry.js
+++ b/src/geometries/vgl-text-geometry.js
@@ -1,6 +1,8 @@
 import { TextBufferGeometry, BufferGeometry, FontLoader } from 'three';
 import VglExtrudeGeometry from './vgl-extrude-geometry';
-import { number, string, boolean } from '../types';
+import {
+  float, int, string, boolean,
+} from '../types';
 
 const fonts = Object.create(null);
 
@@ -19,19 +21,19 @@ export default {
     /** The path or URL to the facetype json file. This can also be a Data URI. */
     font: string,
     /** Size of the text. */
-    size: { type: number, default: 100 },
+    size: { type: float, default: 100 },
     /** Thickness to extrude text. */
-    height: { type: number, default: 50 },
+    height: { type: float, default: 50 },
     /** Number of points on the curves. */
-    curveSegments: { type: number, default: 12 },
+    curveSegments: { type: int, default: 12 },
     /** Turn on bevel. */
     bevelEnabled: boolean,
     /** How deep into text bevel goes. */
-    bevelThickness: { type: number, default: 10 },
+    bevelThickness: { type: float, default: 10 },
     /** How far from text outline is bevel. */
-    bevelSize: { type: number, default: 8 },
+    bevelSize: { type: float, default: 8 },
     /** Number of bevel segments. */
-    bevelSegments: { type: number, default: 3 },
+    bevelSegments: { type: int, default: 3 },
   },
   data() { return { f: undefined }; },
   computed: {
diff --git a/src/geometries/vgl-torus-geometry.js b/src/geometries/vgl-torus-geometry.js
index 5c0eeca..24fc392 100644
--- a/src/geometries/vgl-torus-geometry.js
+++ b/src/geometries/vgl-torus-geometry.js
@@ -1,6 +1,6 @@
 import { TorusBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
-import { number } from '../types';
+import { float, int } from '../types';
 
 /**
  * A component for generating torus geometries,
@@ -13,15 +13,15 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Radius of the torus. */
-    radius: { type: number, default: 1 },
+    radius: { type: float, default: 1 },
     /** Diamiter of the tube. */
-    tube: { type: number, default: 0.4 },
+    tube: { type: float, default: 0.4 },
     /** Number of segments of the tube's section. */
-    radialSegments: { type: number, default: 8 },
+    radialSegments: { type: int, default: 8 },
     /** Number of segments along to the tube length direction. */
-    tubularSegments: { type: number, default: 6 },
+    tubularSegments: { type: int, default: 6 },
     /** The central angle. */
-    arc: { type: number, default: Math.PI * 2 },
+    arc: { type: float, default: Math.PI * 2 },
   },
   computed: {
     inst() {
diff --git a/src/geometries/vgl-torus-knot-geometry.js b/src/geometries/vgl-torus-knot-geometry.js
index bd9c32f..3f04ff1 100644
--- a/src/geometries/vgl-torus-knot-geometry.js
+++ b/src/geometries/vgl-torus-knot-geometry.js
@@ -1,6 +1,6 @@
 import { TorusKnotBufferGeometry } from 'three';
 import VglGeometry from '../core/vgl-geometry';
-import { number } from '../types';
+import { float, int } from '../types';
 
 /**
  * A component for generating torus knot geometries,
@@ -13,23 +13,23 @@ export default {
   mixins: [VglGeometry],
   props: {
     /** Radius of the torus. */
-    radius: { type: number, default: 1 },
+    radius: { type: float, default: 1 },
     /** Diamiter of the tube. */
-    tube: { type: number, default: 0.4 },
+    tube: { type: float, default: 0.4 },
     /** Number of segments of the tube's section. */
-    radialSegments: { type: number, default: 8 },
+    radialSegments: { type: int, default: 8 },
     /** Number of segments along to the tube length direction. */
-    tubularSegments: { type: number, default: 64 },
+    tubularSegments: { type: int, default: 64 },
     /**
      * This value determines how many times the geometry winds
      * around its axis of rotational symmetry.
      */
-    p: { type: number, default: 2 },
+    p: { type: int, default: 2 },
     /**
      * This value determines how many times the geometry winds
      * around a circle in the interior of the torus.
      */
-    q: { type: number, default: 3 },
+    q: { type: int, default: 3 },
   },
   computed: {
     inst() {
diff --git a/src/helpers/vgl-arrow-helper.js b/src/helpers/vgl-arrow-helper.js
index fc49179..18d211d 100644
--- a/src/helpers/vgl-arrow-helper.js
+++ b/src/helpers/vgl-arrow-helper.js
@@ -1,7 +1,8 @@
 import { ArrowHelper, Color, Vector3 } from 'three';
 import VglObject3d from '../core/vgl-object3d';
 import { parseVector3 } from '../parsers';
-import { number, string, vector3 } from '../types';
+import { float, color, vector3 } from '../types';
+import { validateVector3 } from '../validators';
 
 /**
  * An 3D arrow object for visualizing directions,
@@ -14,15 +15,15 @@ export default {
   mixins: [VglObject3d],
   props: {
     /** Direction from origin. */
-    dir: vector3,
+    dir: { type: vector3, validator: validateVector3 },
     /** Length of the arrow. */
-    length: { type: number, default: 1 },
+    length: { type: float, default: 1 },
     /** Color of the arrow. */
-    color: { type: string, default: '#ff0' },
+    color: { type: color, default: '#ff0' },
     /** The length of the head of the arrow. */
-    headLength: number,
+    headLength: float,
     /** The width of the head of the arrow. */
-    headWidth: number,
+    headWidth: float,
   },
   computed: {
     /** The THREE.ArrowHelper instance. */
@@ -53,8 +54,8 @@ export default {
       this.inst.setLength(...len);
       this.vglObject3d.emit();
     },
-    color(color) {
-      this.inst.setColor(new Color(color));
+    color(newColor) {
+      this.inst.setColor(new Color(newColor));
       this.vglObject3d.emit();
     },
   },
diff --git a/src/helpers/vgl-axes-helper.js b/src/helpers/vgl-axes-helper.js
index 1d013ae..813619e 100644
--- a/src/helpers/vgl-axes-helper.js
+++ b/src/helpers/vgl-axes-helper.js
@@ -1,6 +1,6 @@
 import { AxesHelper } from 'three';
 import VglObject3d from '../core/vgl-object3d';
-import { number } from '../types';
+import { float } from '../types';
 
 /**
  * An axis object to visualize the the 3 axes in a simple way,
@@ -14,7 +14,7 @@ export default {
   mixins: [VglObject3d],
   props: {
     /** Size of the lines representing the axes. */
-    size: { type: number, default: 1 },
+    size: { type: float, default: 1 },
   },
   computed: {
     /** The THREE.AxesHelper instance. */
diff --git a/src/helpers/vgl-box-helper.js b/src/helpers/vgl-box-helper.js
index e113e62..b59dd2b 100644
--- a/src/helpers/vgl-box-helper.js
+++ b/src/helpers/vgl-box-helper.js
@@ -1,7 +1,7 @@
 import { BoxHelper } from 'three';
 import VglObject3d from '../core/vgl-object3d';
-import { string, name } from '../types';
-import { nameValidator } from '../validators';
+import { name, color } from '../types';
+import { validateName } from '../validators';
 
 /**
  * A helper component to show the world-axis-aligned bounding box around its parent,
@@ -14,9 +14,9 @@ export default {
   mixins: [VglObject3d],
   props: {
     /** Size of the lines representing the axes. */
-    color: { type: string, default: '#ff0' },
+    color: { type: color, default: '#ff0' },
     /** Name of the object to show the world-axis-aligned boundingbox. */
-    object: { type: name, validator: nameValidator },
+    object: { type: name, required: true, validator: validateName },
   },
   computed: {
     /** The THREE.BoxHelper instance. */
diff --git a/src/helpers/vgl-camera-helper.js b/src/helpers/vgl-camera-helper.js
index c28fc3c..c8f7290 100644
--- a/src/helpers/vgl-camera-helper.js
+++ b/src/helpers/vgl-camera-helper.js
@@ -1,7 +1,7 @@
 import { CameraHelper, Object3D } from 'three';
 import VglObject3d from '../core/vgl-object3d';
 import { name } from '../types';
-import { nameValidator } from '../validators';
+import { validateName } from '../validators';
 
 /**
  * This helps with visualizing what a camera contains in its frustum,
@@ -15,7 +15,7 @@ export default {
   mixins: [VglObject3d],
   props: {
     /** Name of the camera to visualize. */
-    camera: { type: name, required: true, validator: nameValidator },
+    camera: { type: name, required: true, validator: validateName },
   },
   data: () => ({
     /** If camera specified by the name exists or not. Do not set this data manually. */
diff --git a/src/helpers/vgl-directional-light-helper.js b/src/helpers/vgl-directional-light-helper.js
index 594c14a..e771cd5 100644
--- a/src/helpers/vgl-directional-light-helper.js
+++ b/src/helpers/vgl-directional-light-helper.js
@@ -1,6 +1,7 @@
 import { DirectionalLightHelper, Object3D } from 'three';
 import VglObject3d from '../core/vgl-object3d';
-import { string, number } from '../types';
+import { name, float, color } from '../types';
+import { validateName } from '../validators';
 
 /**
  * A helper component to assist with visualizing a DirectionalLight's effect on the scene,
@@ -13,11 +14,11 @@ export default {
   mixins: [VglObject3d],
   props: {
     /** If this is not the set the helper will take the color of the light. */
-    color: { type: string },
+    color,
     /** Dimensions of the plane. */
-    size: { type: number, default: 1 },
+    size: { type: float, default: 1 },
     /** Name of the directional light being visualized. */
-    light: string,
+    light: { type: name, required: true, validator: validateName },
   },
   data: () => ({
     /**
@@ -56,10 +57,10 @@ export default {
       }
     },
     light: {
-      handler(name, oldName) {
+      handler(newName, oldName) {
         if (oldName !== undefined) this.vglNamespace.object3ds.unlisten(oldName, this.setLightUuid);
-        if (name !== undefined) {
-          this.vglNamespace.object3ds.listen(name, this.setLightUuid);
+        if (newName !== undefined) {
+          this.vglNamespace.object3ds.listen(newName, this.setLightUuid);
           const light = this.vglNamespace.object3ds.get(this.light);
           this.setLightUuid(light);
         }
@@ -67,9 +68,9 @@ export default {
       immediate: true,
     },
     color: {
-      handler(color) {
+      handler(newColor) {
         if (!this.lightUuid) return;
-        this.inst.color = color;
+        this.inst.color = newColor;
         this.inst.update();
       },
       immediate: true,
diff --git a/src/helpers/vgl-grid-helper.js b/src/helpers/vgl-grid-helper.js
index e654798..349d18d 100644
--- a/src/helpers/vgl-grid-helper.js
+++ b/src/helpers/vgl-grid-helper.js
@@ -1,6 +1,6 @@
 import { GridHelper } from 'three';
 import VglObject3d from '../core/vgl-object3d';
-import { number, string } from '../types';
+import { float, int, color } from '../types';
 
 /**
  * A component to define grids,
@@ -14,13 +14,13 @@ export default {
   mixins: [VglObject3d],
   props: {
     /** The size of the grid. */
-    size: { type: number, default: 10 },
+    size: { type: float, default: 10 },
     /** The number of divisions across the grid. */
-    divisions: { type: number, default: 10 },
+    divisions: { type: int, default: 10 },
     /** The color of the centerline. */
-    colorCenterLine: { type: string, default: '#444444' },
+    colorCenterLine: { type: color, default: '#444444' },
     /** The color of the lines of the grid. */
-    colorGrid: { type: string, default: '#888888' },
+    colorGrid: { type: color, default: '#888888' },
   },
   computed: {
     /** The THREE.GridHelper instance. */
diff --git a/src/helpers/vgl-polar-grid-helper.js b/src/helpers/vgl-polar-grid-helper.js
index 0fed747..183cb4e 100644
--- a/src/helpers/vgl-polar-grid-helper.js
+++ b/src/helpers/vgl-polar-grid-helper.js
@@ -1,6 +1,6 @@
 import { PolarGridHelper } from 'three';
 import VglObject3d from '../core/vgl-object3d';
-import { number, string } from '../types';
+import { float, int, color } from '../types';
 
 /**
  * A component to define polar grids,
@@ -14,20 +14,20 @@ export default {
   mixins: [VglObject3d],
   props: {
     /** The radius of the polar grid. This can be any positive number. */
-    radius: { type: number, default: 10 },
+    radius: { type: float, default: 10 },
     /** The number of radial lines. This can be any positive integer. */
-    radials: { type: number, default: 16 },
+    radials: { type: int, default: 16 },
     /** The number of circles. This can be any positive integer. */
-    circles: { type: number, default: 8 },
+    circles: { type: int, default: 8 },
     /**
      * The number of line segments used for each circle.
      * This can be any positive integer that is 3 or greater.
      */
-    divisions: { type: number, default: 64 },
+    divisions: { type: int, default: 64 },
     /** The first color used for grid elements. */
-    color1: { type: string, default: '#444444' },
+    color1: { type: color, default: '#444444' },
     /** The second color used for grid elements. */
-    color2: { type: string, default: '#888888' },
+    color2: { type: color, default: '#888888' },
   },
   computed: {
     /** The THREE.PolarGridHelper instance. */
diff --git a/src/helpers/vgl-rect-area-light-helper.js b/src/helpers/vgl-rect-area-light-helper.js
index f0287be..d9f7061 100644
--- a/src/helpers/vgl-rect-area-light-helper.js
+++ b/src/helpers/vgl-rect-area-light-helper.js
@@ -1,6 +1,7 @@
 import { RectAreaLightHelper, Object3D } from 'three';
 import VglObject3d from '../core/vgl-object3d';
-import { string } from '../types';
+import { name, color } from '../types';
+import { validateName } from '../validators';
 
 /**
  * Creates a visual aid for a RectAreaLight, corresponding [THREE.RectAreaLightHelper](https://threejs.org/docs/#api/en/helpers/RectAreaLightHelper).
@@ -12,9 +13,9 @@ export default {
   mixins: [VglObject3d],
   props: {
     /** If this is not the set the helper will take the color of the light. */
-    color: { type: string },
+    color,
     /** Name of the RectAreaLight being visualized. */
-    light: { type: string },
+    light: { type: name, required: true, validator: validateName },
   },
   data: () => ({
     /**
@@ -53,10 +54,10 @@ export default {
       }
     },
     light: {
-      handler(name, oldName) {
+      handler(newName, oldName) {
         if (oldName !== undefined) this.vglNamespace.object3ds.unlisten(oldName, this.setLightUuid);
-        if (name !== undefined) {
-          this.vglNamespace.object3ds.listen(name, this.setLightUuid);
+        if (newName !== undefined) {
+          this.vglNamespace.object3ds.listen(newName, this.setLightUuid);
           const light = this.vglNamespace.object3ds.get(this.light);
           this.setLightUuid(light);
         }
@@ -64,9 +65,9 @@ export default {
       immediate: true,
     },
     color: {
-      handler(color) {
+      handler(newColor) {
         if (!this.lightUuid) return;
-        this.inst.color = color;
+        this.inst.color = newColor;
         this.inst.update();
       },
       immediate: true,
diff --git a/src/helpers/vgl-spot-light-helper.js b/src/helpers/vgl-spot-light-helper.js
index b30012b..d7aae8a 100644
--- a/src/helpers/vgl-spot-light-helper.js
+++ b/src/helpers/vgl-spot-light-helper.js
@@ -1,6 +1,7 @@
 import { SpotLightHelper, Object3D } from 'three';
 import VglObject3d from '../core/vgl-object3d';
-import { string } from '../types';
+import { color, name } from '../types';
+import { validateName } from '../validators';
 
 /**
  * This component displays a cone shaped helper object for a SpotLight,
@@ -13,9 +14,9 @@ export default {
   mixins: [VglObject3d],
   props: {
     /** If this is not the set the helper will take the color of the light. */
-    color: { type: string },
+    color,
     /** Name of the spot light being visualized. */
-    light: string,
+    light: { type: name, required: true, validator: validateName },
   },
   data: () => ({
     /**
@@ -54,10 +55,10 @@ export default {
       }
     },
     light: {
-      handler(name, oldName) {
+      handler(newName, oldName) {
         if (oldName !== undefined) this.vglNamespace.object3ds.unlisten(oldName, this.setLightUuid);
-        if (name !== undefined) {
-          this.vglNamespace.object3ds.listen(name, this.setLightUuid);
+        if (newName !== undefined) {
+          this.vglNamespace.object3ds.listen(newName, this.setLightUuid);
           const light = this.vglNamespace.object3ds.get(this.light);
           this.setLightUuid(light);
         }
@@ -65,9 +66,9 @@ export default {
       immediate: true,
     },
     color: {
-      handler(color) {
+      handler(newColor) {
         if (!this.lightUuid) return;
-        this.inst.color = color;
+        this.inst.color = newColor;
         this.inst.update();
       },
       immediate: true,
diff --git a/src/lights/vgl-hemisphere-light.js b/src/lights/vgl-hemisphere-light.js
index 160a9ea..c26e683 100644
--- a/src/lights/vgl-hemisphere-light.js
+++ b/src/lights/vgl-hemisphere-light.js
@@ -1,6 +1,6 @@
 import { HemisphereLight } from 'three';
 import VglLight from './vgl-light';
-import { string } from '../types';
+import { color } from '../types';
 
 /**
  * A light source positioned directly above the scene, with color fading from the sky color to the
@@ -14,7 +14,7 @@ export default {
   mixins: [VglLight],
   props: {
     /** The light's ground color */
-    groundColor: { type: string, default: '#fff' },
+    groundColor: { type: color, default: '#fff' },
   },
   computed: {
     /** The THREE.HemisphereLight instance. */
diff --git a/src/lights/vgl-light.js b/src/lights/vgl-light.js
index 8743311..2b83f48 100644
--- a/src/lights/vgl-light.js
+++ b/src/lights/vgl-light.js
@@ -1,6 +1,6 @@
 import { Light } from 'three';
 import VglObject3d from '../core/vgl-object3d';
-import { string, number } from '../types';
+import { color, float } from '../types';
 
 /**
  * Abstract mixin component for lights,
@@ -13,9 +13,9 @@ export default {
   mixins: [VglObject3d],
   props: {
     /** CSS style color of the light. */
-    color: { type: string, default: '#fff' },
+    color: { type: color, default: '#fff' },
     /** Numeric value of the light's strength/intensity. */
-    intensity: { type: number, default: 1 },
+    intensity: { type: float, default: 1 },
   },
   computed: {
     /** The THREE.Light instance. */
@@ -29,8 +29,8 @@ export default {
       },
       immediate: true,
     },
-    color(color) {
-      this.inst.color.setStyle(color);
+    color(newColor) {
+      this.inst.color.setStyle(newColor);
       this.vglObject3d.emit();
     },
     intensity(intensity) {
diff --git a/src/lights/vgl-point-light.js b/src/lights/vgl-point-light.js
index 87a7437..6b2328c 100644
--- a/src/lights/vgl-point-light.js
+++ b/src/lights/vgl-point-light.js
@@ -1,6 +1,6 @@
 import { PointLight } from 'three';
 import VglLight from './vgl-light';
-import { number } from '../types';
+import { float } from '../types';
 
 /**
  * A light that gets emitted from a single point in all directions, corresponding [THREE.PointLight](https://threejs.org/docs/index.html#api/lights/PointLight). A common use case for this is to replicate the light emitted from a bare lightbulb. This light can cast shadows.
@@ -15,12 +15,12 @@ export default {
      * The distance from the light where the intensity is 0.
      * When set to 0, then the light never stops.
      */
-    distance: { type: number, default: 0 },
+    distance: { type: float, default: 0 },
     /**
      * The amount the light dims along the distance of the light.
      * For physically correct lighting, set this to 2.
      */
-    decay: { type: number, default: 1 },
+    decay: { type: float, default: 1 },
   },
   computed: {
     /** The THREE.PointLight instance. */
diff --git a/src/lights/vgl-rect-area-light.js b/src/lights/vgl-rect-area-light.js
index cae7d84..b9a88dc 100644
--- a/src/lights/vgl-rect-area-light.js
+++ b/src/lights/vgl-rect-area-light.js
@@ -1,6 +1,6 @@
 import { RectAreaLight } from 'three';
 import VglLight from './vgl-light';
-import { number } from '../types';
+import { float } from '../types';
 
 /**
  * RectAreaLight emits light uniformly across the face a rectangular plane. See
@@ -15,9 +15,9 @@ export default {
   mixins: [VglLight],
   props: {
     /** Width of the light. */
-    width: { type: number, default: 10 },
+    width: { type: float, default: 10 },
     /** Height of the light. */
-    height: { type: number, default: 10 },
+    height: { type: float, default: 10 },
   },
   computed: {
     /** The THREE.RectAreaLight instance. */
diff --git a/src/lights/vgl-spot-light.js b/src/lights/vgl-spot-light.js
index 4ac2963..4456e90 100644
--- a/src/lights/vgl-spot-light.js
+++ b/src/lights/vgl-spot-light.js
@@ -1,7 +1,8 @@
 import { SpotLight } from 'three';
 import VglLight from './vgl-light';
 import { parseVector3 } from '../parsers';
-import { number, vector3 } from '../types';
+import { vector3, float } from '../types';
+import { validateVector3 } from '../validators';
 
 /**
  * This light gets emitted from a single point in one direction, along a cone that increases in size the further from the light it gets. Corresponding [THREE.SpotLight](https://threejs.org/docs/index.html#api/lights/SpotLight). This light can cast shadows.
@@ -16,24 +17,24 @@ export default {
      * The distance from the light where the intensity is 0.
      * When set to 0, then the light never stops.
      */
-    distance: { type: number, default: 0 },
+    distance: { type: float, default: 0 },
     /**
      * The amount the light dims along the distance of the light.
      * For physically correct lighting, set this to 2.
      */
-    decay: { type: number, default: 1 },
+    decay: { type: float, default: 1 },
     /**
      * Maximum extent of the spotlight, in radians, from its direction.
      * Should be no more than Math.PI/2.
      */
-    angle: { type: number, default: Math.PI / 3 },
+    angle: { type: float, default: Math.PI / 3 },
     /**
      * Percent of the spotlight cone that is attenuated due to penumbra.
      * Takes values between zero and 1.
      */
-    penumbra: { type: number, default: 0 },
+    penumbra: { type: float, default: 0 },
     /** The spotlight's pointing position. */
-    target: vector3,
+    target: { type: vector3, validator: validateVector3 },
   },
   computed: {
     /** The THREE.SpotLight instance. */
diff --git a/src/materials/vgl-line-basic-material.js b/src/materials/vgl-line-basic-material.js
index c1c3581..308d3b4 100644
--- a/src/materials/vgl-line-basic-material.js
+++ b/src/materials/vgl-line-basic-material.js
@@ -1,6 +1,6 @@
 import { LineBasicMaterial } from 'three';
 import VglMaterial from './vgl-material';
-import { string, number } from '../types';
+import { string, color, float } from '../types';
 
 /**
  * A material for drawing wireframe-style geometries,
@@ -13,13 +13,13 @@ export default {
   mixins: [VglMaterial],
   props: {
     /** CSS style color of the material. */
-    color: { type: string, default: '#fff' },
+    color: { type: color, default: '#fff' },
     /** The line thickness. */
-    linewidth: { type: number, default: 1 },
+    linewidth: { type: float, default: 1 },
     /** Define appearance of line ends. Possible values are "butt", "round" and "square". */
-    linecap: { type: string, default: 'round' },
+    linecap: { type: string, default: 'round', validator: (v) => /^(butt|round|square)$/.test(v) },
     /** Define appearance of line joints. Possible values are "round", "bevel" and "miter". */
-    linejoin: { type: string, default: 'round' },
+    linejoin: { type: string, default: 'round', validator: (v) => /^(round|bevel|miter)$/.test(v) },
   },
   computed: {
     /** The THREE.LineBasicMaterial instance. */
@@ -37,8 +37,8 @@ export default {
       },
       immediate: true,
     },
-    color(color) {
-      this.inst.color.setStyle(color);
+    color(newColor) {
+      this.inst.color.setStyle(newColor);
       this.update();
     },
     linewidth(width) {
diff --git a/src/materials/vgl-line-dashed-material.js b/src/materials/vgl-line-dashed-material.js
index d509251..a719193 100644
--- a/src/materials/vgl-line-dashed-material.js
+++ b/src/materials/vgl-line-dashed-material.js
@@ -1,6 +1,6 @@
 import { LineDashedMaterial } from 'three';
 import VglMaterial from './vgl-material';
-import { string, number } from '../types';
+import { color, float } from '../types';
 
 /**
  * A material for drawing wireframe-style geometries,
@@ -13,13 +13,13 @@ export default {
   mixins: [VglMaterial],
   props: {
     /** CSS style color of the material. */
-    color: { type: string, default: '#fff' },
+    color: { type: color, default: '#fff' },
     /** The line thickness. */
-    linewidth: { type: number, default: 1 },
+    linewidth: { type: float, default: 1 },
     /** The size of the dash. This is both the gap with the stroke. */
-    dashSize: { type: number, default: 3 },
+    dashSize: { type: float, default: 3 },
     /** The size of the gap. */
-    gapSize: { type: number, default: 1 },
+    gapSize: { type: float, default: 1 },
   },
   computed: {
     /** The THREE.LineDashedMaterial instance. */
@@ -37,8 +37,8 @@ export default {
       },
       immediate: true,
     },
-    color(color) {
-      this.inst.color.setStyle(color);
+    color(newColor) {
+      this.inst.color.setStyle(newColor);
       this.update();
     },
     linewidth(width) {
diff --git a/src/materials/vgl-material.js b/src/materials/vgl-material.js
index be1905d..e03ae0b 100644
--- a/src/materials/vgl-material.js
+++ b/src/materials/vgl-material.js
@@ -1,14 +1,8 @@
 import {
-  Material,
-  NoColors,
-  VertexColors,
-  FaceColors,
-  FrontSide,
-  BackSide,
-  DoubleSide,
+  Material, NoColors, VertexColors, FaceColors, FrontSide, BackSide, DoubleSide,
 } from 'three';
 import { string, name } from '../types';
-import { nameValidator } from '../validators';
+import { validateName } from '../validators';
 
 const vertexColors = {
   no: NoColors,
@@ -35,7 +29,7 @@ export default {
   },
   props: {
     /** Name of the material. */
-    name: { type: name, validator: nameValidator },
+    name: { type: name, required: true, validator: validateName },
     /** Defines which side of faces will be rendered. front, back or double. */
     side: { type: string, default: 'front' },
     /** Defines whether vertex coloring is used. Other options are 'vertex' and 'face'. */
diff --git a/src/materials/vgl-mesh-basic-material.js b/src/materials/vgl-mesh-basic-material.js
index b628c73..f27d5f9 100644
--- a/src/materials/vgl-mesh-basic-material.js
+++ b/src/materials/vgl-mesh-basic-material.js
@@ -1,6 +1,7 @@
 import { MeshBasicMaterial } from 'three';
 import { VglMaterialWithMap } from '../mixins';
-import { string } from '../types';
+import { name, color } from '../types';
+import { validateName } from '../validators';
 
 /**
  * A material for drawing geometries in a simple shaded (flat or wireframe) way,
@@ -14,9 +15,9 @@ export default {
   mixins: [VglMaterialWithMap],
   props: {
     /** CSS style color of the material. */
-    color: { type: string, default: '#fff' },
+    color: { type: color, default: '#fff' },
     /** The color map of the material. */
-    map: string,
+    map: { type: name, validator: validateName },
   },
   computed: {
     /** The THREE.MeshBasicMaterial instance. */
@@ -27,8 +28,8 @@ export default {
       handler(inst) { inst.color.setStyle(this.color); },
       immediate: true,
     },
-    color(color) {
-      this.inst.color.setStyle(color);
+    color(newColor) {
+      this.inst.color.setStyle(newColor);
       this.update();
     },
   },
diff --git a/src/materials/vgl-mesh-depth-material.js b/src/materials/vgl-mesh-depth-material.js
index baac882..a1e9a2e 100644
--- a/src/materials/vgl-mesh-depth-material.js
+++ b/src/materials/vgl-mesh-depth-material.js
@@ -1,6 +1,7 @@
 import { MeshDepthMaterial } from 'three';
 import { VglMaterialWithMap } from '../mixins';
-import { string, boolean } from '../types';
+import { name, boolean } from '../types';
+import { validateName } from '../validators';
 
 /**
  * A material for drawing geometry by depth,
@@ -16,7 +17,7 @@ export default {
     /** Whether the material is affected by fog. */
     fog: boolean,
     /** The color map of the material. */
-    map: string,
+    map: { type: name, validator: validateName },
   },
   computed: {
     /** The THREE.MeshDepthMaterial instance. */
diff --git a/src/materials/vgl-mesh-lambert-material.js b/src/materials/vgl-mesh-lambert-material.js
index 02cf938..a633505 100644
--- a/src/materials/vgl-mesh-lambert-material.js
+++ b/src/materials/vgl-mesh-lambert-material.js
@@ -1,6 +1,7 @@
 import { MeshLambertMaterial } from 'three';
 import { VglMaterialWithMap } from '../mixins';
-import { string } from '../types';
+import { name, color } from '../types';
+import { validateName } from '../validators';
 
 /**
  * A material for non-shiny surfaces, without specular highlights,
@@ -17,9 +18,9 @@ export default {
   mixins: [VglMaterialWithMap],
   props: {
     /** CSS style color of the material. */
-    color: { type: string, default: '#fff' },
+    color: { type: color, default: '#fff' },
     /** The color map of the material. */
-    map: string,
+    map: { type: name, validator: validateName },
   },
   computed: {
     /** The THREE.MeshLambertMaterial instance. */
@@ -30,8 +31,8 @@ export default {
       handler(inst) { inst.color.setStyle(this.color); },
       immediate: true,
     },
-    color(color) {
-      this.inst.color.setStyle(color);
+    color(newColor) {
+      this.inst.color.setStyle(newColor);
       this.update();
     },
   },
diff --git a/src/materials/vgl-mesh-phong-material.js b/src/materials/vgl-mesh-phong-material.js
index 52aed89..db52ff4 100644
--- a/src/materials/vgl-mesh-phong-material.js
+++ b/src/materials/vgl-mesh-phong-material.js
@@ -1,6 +1,7 @@
 import { MeshPhongMaterial } from 'three';
 import { VglMaterialWithMap } from '../mixins';
-import { string, number } from '../types';
+import { color, name, float } from '../types';
+import { validateName } from '../validators';
 
 /**
  * A material for shiny surfaces with specular highlights,
@@ -13,13 +14,13 @@ export default {
   mixins: [VglMaterialWithMap],
   props: {
     /** CSS style color of the material. */
-    color: { type: string, default: '#fff' },
+    color: { type: color, default: '#fff' },
     /** The color map of the material. */
-    map: string,
+    map: { type: name, validator: validateName },
     /** Specular color of the material. */
-    specular: { type: string, default: '#111111' },
+    specular: { type: color, default: '#111111' },
     /** How shiny the specular highlight is. A higher value gives a sharper highlight. */
-    shininess: { type: number, default: 30 },
+    shininess: { type: float, default: 30 },
   },
   computed: {
     /** The THREE.MeshPhongMaterial instance. */
@@ -36,8 +37,8 @@ export default {
       },
       immediate: true,
     },
-    color(color) {
-      this.inst.color.setStyle(color);
+    color(newColor) {
+      this.inst.color.setStyle(newColor);
       this.update();
     },
     specular(specular) {
diff --git a/src/materials/vgl-mesh-physical-material.js b/src/materials/vgl-mesh-physical-material.js
index 72ee632..6a60d7f 100644
--- a/src/materials/vgl-mesh-physical-material.js
+++ b/src/materials/vgl-mesh-physical-material.js
@@ -1,6 +1,6 @@
 import { MeshPhysicalMaterial } from 'three';
 import VglMeshStandardMaterial from './vgl-mesh-standard-material';
-import { number } from '../types';
+import { float } from '../types';
 
 /**
  * An extension of the mesh standard material that allows for greater control over reflectivity,
@@ -13,11 +13,11 @@ export default {
   mixins: [VglMeshStandardMaterial],
   props: {
     /** ClearCoat level, from 0.0 to 1.0. */
-    clearcoat: { type: number, default: 0 },
+    clearcoat: { type: float, default: 0 },
     /** How rough the clearCoat appears, from 0.0 to 1.0. */
-    clearcoatRoughness: { type: number, default: 0 },
+    clearcoatRoughness: { type: float, default: 0 },
     /** Degree of reflectivity, from 0.0 to 1.0. */
-    reflectivity: { type: number, default: 0.5 },
+    reflectivity: { type: float, default: 0.5 },
   },
   computed: {
     /** The THREE.MeshPhysicalMaterial instance. */
diff --git a/src/materials/vgl-mesh-standard-material.js b/src/materials/vgl-mesh-standard-material.js
index eb513d7..f68258b 100644
--- a/src/materials/vgl-mesh-standard-material.js
+++ b/src/materials/vgl-mesh-standard-material.js
@@ -1,6 +1,7 @@
 import { MeshStandardMaterial } from 'three';
 import { VglMaterialWithMap } from '../mixins';
-import { string } from '../types';
+import { color, name } from '../types';
+import { validateName } from '../validators';
 
 /**
  * A standard physically based material,
@@ -14,9 +15,9 @@ export default {
   mixins: [VglMaterialWithMap],
   props: {
     /** CSS style color of the material. */
-    color: { type: string, default: '#fff' },
+    color: { type: color, default: '#fff' },
     /** The color map of the material. */
-    map: string,
+    map: { type: name, validator: validateName },
   },
   computed: {
     /** The THREE.MeshStandardMaterial instance. */
@@ -27,8 +28,8 @@ export default {
       handler(inst) { inst.color.setStyle(this.color); },
       immediate: true,
     },
-    color(color) {
-      this.inst.color.setStyle(color);
+    color(newColor) {
+      this.inst.color.setStyle(newColor);
       this.update();
     },
   },
diff --git a/src/materials/vgl-points-material.js b/src/materials/vgl-points-material.js
index c11563b..4a0987d 100644
--- a/src/materials/vgl-points-material.js
+++ b/src/materials/vgl-points-material.js
@@ -1,6 +1,6 @@
 import { PointsMaterial } from 'three';
 import VglMaterial from './vgl-material';
-import { string, number, boolean } from '../types';
+import { boolean, color, float } from '../types';
 
 /**
  * The default material used by [VglPoints](vgl-points),
@@ -13,9 +13,9 @@ export default {
   mixins: [VglMaterial],
   props: {
     /** CSS style color of the material. */
-    color: { type: string, default: '#fff' },
+    color: { type: color, default: '#fff' },
     /** The size of the points. */
-    size: { type: number, default: 1 },
+    size: { type: float, default: 1 },
     /** Specify whether points' size will get smaller with the distance. */
     disableSizeAttenuation: boolean,
   },
@@ -34,8 +34,8 @@ export default {
       },
       immediate: true,
     },
-    color(color) {
-      this.inst.color.setStyle(color);
+    color(newColor) {
+      this.inst.color.setStyle(newColor);
       this.update();
     },
     size(size) {
diff --git a/src/materials/vgl-shader-material.js b/src/materials/vgl-shader-material.js
index cb12522..eacf571 100644
--- a/src/materials/vgl-shader-material.js
+++ b/src/materials/vgl-shader-material.js
@@ -1,6 +1,6 @@
 import { ShaderMaterial } from 'three';
 import { VglMaterialWithMap } from '../mixins';
-import { boolean, number, string } from '../types';
+import { boolean, string, float } from '../types';
 
 /**
  * A material for drawing geometries with custom vertex or fragment shaders, corresponding to
@@ -72,7 +72,7 @@ export default {
      * Controls wireframe thickness. Due to limitations of the OpenGL Core Profile with the WebGL
      * renderer on most platforms `linewidth` will always be 1 regardless of the set value.
      */
-    linewidth: { type: number, default: 1.0 },
+    linewidth: { type: float, default: 1.0 },
     /** Define whether the material is rendered with flat shading. */
     flatShading: { type: boolean, default: false },
     /**
@@ -102,7 +102,7 @@ export default {
      * Controls wireframe thickness. Due to limitations of the OpenGL Core Profile with the WebGL
      * renderer on most platforms `linewidth` will always be 1 regardless of the set value.
      */
-    wireframeLinewidth: { type: number, default: 1.0 },
+    wireframeLinewidth: { type: float, default: 1.0 },
   },
 
   computed: {
diff --git a/src/materials/vgl-sprite-material.js b/src/materials/vgl-sprite-material.js
index 8c0546c..c004330 100644
--- a/src/materials/vgl-sprite-material.js
+++ b/src/materials/vgl-sprite-material.js
@@ -1,7 +1,7 @@
 import { SpriteMaterial } from 'three';
 import { VglMaterialWithMap } from '../mixins';
-import { string, name } from '../types';
-import { nameValidator } from '../validators';
+import { name, color } from '../types';
+import { validateName } from '../validators';
 
 /**
  * A material for a use with a [VglSprite](vgl-sprite) component,
@@ -14,9 +14,9 @@ export default {
   mixins: [VglMaterialWithMap],
   props: {
     /** CSS style color of the material. */
-    color: { type: string, default: '#fff' },
+    color: { type: color, default: '#fff' },
     /** The texture map of the material. */
-    map: { type: name, validator: nameValidator },
+    map: { type: name, validator: validateName },
   },
   computed: {
     /** The THREE.SpriteMaterial instance. */
@@ -27,8 +27,8 @@ export default {
       handler(inst) { inst.color.setStyle(this.color); },
       immediate: true,
     },
-    color(color) {
-      this.inst.color.setStyle(color);
+    color(newColor) {
+      this.inst.color.setStyle(newColor);
       this.update();
     },
   },
diff --git a/src/objects/vgl-line.js b/src/objects/vgl-line.js
index 198fc22..72811c5 100644
--- a/src/objects/vgl-line.js
+++ b/src/objects/vgl-line.js
@@ -1,7 +1,7 @@
 import { Line } from 'three';
 import { VglObject3dWithMatarialAndGeometry } from '../mixins';
 import { name } from '../types';
-import { nameValidator } from '../validators';
+import { validateName } from '../validators';
 
 /**
  * A continuous line component,
@@ -14,9 +14,9 @@ export default {
   mixins: [VglObject3dWithMatarialAndGeometry],
   props: {
     /** Name of the geometry, representing the line segment(s). */
-    geometry: { type: name, validator: nameValidator },
+    geometry: { type: name, validator: validateName },
     /** Name of the material for the line. */
-    material: { type: name, validator: nameValidator },
+    material: { type: name, validator: validateName },
   },
   computed: {
     /** The THREE.Line instance. */
diff --git a/src/objects/vgl-mesh.js b/src/objects/vgl-mesh.js
index 6c7cf68..43cd7fc 100644
--- a/src/objects/vgl-mesh.js
+++ b/src/objects/vgl-mesh.js
@@ -1,7 +1,7 @@
 import { Mesh } from 'three';
 import { VglObject3dWithMatarialAndGeometry } from '../mixins';
 import { name, names } from '../types';
-import { nameValidator, namesValidator } from '../validators';
+import { validateName, validateNames } from '../validators';
 
 /**
  * A component representing triangular polygon mesh based objects,
@@ -14,14 +14,14 @@ export default {
   mixins: [VglObject3dWithMatarialAndGeometry],
   props: {
     /** Name of the geometry, defining the object's structure. */
-    geometry: { type: name, validator: nameValidator },
+    geometry: { type: name, validator: validateName },
     /**
      * A Material name or an array of Material name, defining the object's appearance.
      *
      * A single material will apply the material to all object's faces meanwhile
      * an array of material will apply each material to the matching index object's face
      */
-    material: { type: names, validator: namesValidator },
+    material: { type: names, validator: validateNames },
   },
   computed: {
     /** The THREE.Mesh instance. */
diff --git a/src/objects/vgl-points.js b/src/objects/vgl-points.js
index 7191a90..b17b116 100644
--- a/src/objects/vgl-points.js
+++ b/src/objects/vgl-points.js
@@ -1,7 +1,7 @@
 import { Points } from 'three';
 import { VglObject3dWithMatarialAndGeometry } from '../mixins';
 import { name } from '../types';
-import { nameValidator } from '../validators';
+import { validateName } from '../validators';
 
 /**
  * A component for displaying points,
@@ -14,9 +14,9 @@ export default {
   mixins: [VglObject3dWithMatarialAndGeometry],
   props: {
     /** Name of the geometry, defining the object's structure. */
-    geometry: { type: name, validator: nameValidator },
+    geometry: { type: name, validator: validateName },
     /** Name of the material, defining the object's appearance. */
-    material: { type: name, validator: nameValidator },
+    material: { type: name, validator: validateName },
   },
   computed: {
     /** The THREE.Points instance. */
diff --git a/src/objects/vgl-sprite.js b/src/objects/vgl-sprite.js
index 36020f3..b8ee0f6 100644
--- a/src/objects/vgl-sprite.js
+++ b/src/objects/vgl-sprite.js
@@ -1,7 +1,7 @@
 import { Sprite } from 'three';
 import { VglObject3dWithMatarial } from '../mixins';
 import { name } from '../types';
-import { nameValidator } from '../validators';
+import { validateName } from '../validators';
 
 /**
  * A sprite component corresponding [THREE.Sprite](https://threejs.org/docs/index.html#api/objects/Sprite).
@@ -14,7 +14,7 @@ export default {
   mixins: [VglObject3dWithMatarial],
   props: {
     /** Name of the material, defining the object's appearance. */
-    material: { type: name, validator: nameValidator },
+    material: { type: name, validator: validateName },
   },
   computed: {
     /** The THREE.Sprite instance. */
diff --git a/src/parsers.js b/src/parsers.js
index f487572..2f7513e 100644
--- a/src/parsers.js
+++ b/src/parsers.js
@@ -1,83 +1,112 @@
 import {
-  Vector2,
-  Vector3,
-  Euler,
-  Spherical,
-  Quaternion,
-  Fog,
-  Color,
+  Vector2, Vector3, Euler, Quaternion, Spherical, Color, Fog,
 } from 'three';
 
 /**
- * Returns a parsed quaternion object.
+ * Parses a prop value as names type.
+ *
+ * @param {string|string[]} names - Prop value.
+ * @return {string[]} Parsed array of names.
  */
-export function parseQuaternion(str) {
-  return str.isQuaternion ? str : new Quaternion(...str.trim().split(/\s+/).map((elm) => parseFloat(elm)));
+export function parseNames(names) {
+  return Array.isArray(names) ? names : names.trim().split(/\s+/);
 }
 
 /**
- * Returns a parsed vector3 object.
+ * Parses a prop value as color type.
+ *
+ * @param {string|number|Color} color - Prop value.
+ * @return {Color} Parsed THREE.Color instance.
  */
-export function parseVector3(str) {
-  return str.isVector3 ? str : new Vector3(...str.trim().split(/\s+/).map((elm) => parseFloat(elm)));
+export function parseColor(color) {
+  return color.isColor ? color : new Color(color);
 }
 
 /**
- * Returns a parsed vector2 object.
+ * Parses a prop value as vector2 type.
+ *
+ * @param {string|(string|number)[]|Vector2} vector - Prop value.
+ * @return {Vector2} Parsed THREE.Vector2 instance.
  */
-export function parseVector2(str) {
-  if (str.isVector2) return str;
-  if (Array.isArray(str)) {
-    return new Vector2(...(str.map((e) => parseFloat(e))));
-  }
-  return new Vector2(...str.trim().split(/\s+/).map((elm) => parseFloat(elm)));
+export function parseVector2(vector) {
+  if (vector.isVector2) return vector;
+  const coods = Array.isArray(vector) ? vector : vector.trim().split(/\s+/);
+  return new Vector2(...coods.map(parseFloat));
 }
 
 /**
- * Returns a parsed euler object.
+ * Parses a prop value as vector3 type.
+ *
+ * @param {string|(string|number)[]|Vector3} vector - Prop value.
+ * @return {Vector3} Parsed THREE.Vector3 instance.
  */
-export function parseEuler(str) {
-  return str.isEuler ? str : new Euler(...str.trim().split(/\s+/).map((elm, i) => (i === 3 ? elm : parseFloat(elm))));
+export function parseVector3(vector) {
+  if (vector.isVector3) return vector;
+  const coods = Array.isArray(vector) ? vector : vector.trim().split(/\s+/);
+  return new Vector3(...coods.map(parseFloat));
 }
 
 /**
- * Returns a parsed spherical object.
+ * Parses a prop value as euler type.
+ *
+ * @param {string|(string|number)[]|Euler} euler - Prop value.
+ * @return {Euler} Parsed THREE.Euler instance.
  */
-export function parseSpherical(str) {
-  return str.isSpherical ? str : new Spherical(...str.trim().split(/\s+/).map((elm) => parseFloat(elm))).makeSafe();
+export function parseEuler(euler) {
+  if (euler.isEuler) return euler;
+  const coods = Array.isArray(euler) ? euler : euler.trim().split(/\s+/);
+  return new Euler(...coods.slice(0, 3).map(parseFloat), coods[3]);
 }
 
 /**
- * Returns a parsed array.
+ * Parses a prop value as quaternion type.
+ *
+ * @param {string|(string|number)[]|Quaternion} quaternion - Prop value.
+ * @return {Quaternion} Parsed THREE.Quaternion instance.
  */
-export function parseArray(str) {
-  return Array.isArray(str) ? str : str.split(',');
+export function parseQuaternion(quaternion) {
+  if (quaternion.isQuaternion) return quaternion;
+  const coods = Array.isArray(quaternion) ? quaternion : quaternion.trim().split(/\s+/);
+  return new Quaternion(...coods.map(parseFloat));
 }
 
 /**
- * Returns a parsed array of vector2.
+ * Parses a prop value as spherical type.
+ *
+ * @param {string|(string|number)[]|Spherical} spherical - Prop value.
+ * @return {Spherical} Parsed THREE.Spherical instance.
  */
-export function parseVector2Array(str) {
-  return parseArray(str).map((elm) => parseVector2(elm));
+export function parseSpherical(spherical) {
+  if (spherical instanceof Spherical) return spherical;
+  const coods = Array.isArray(spherical) ? spherical : spherical.trim().split(/\s+/);
+  return new Spherical(...coods.map(parseFloat)).makeSafe();
 }
 
 /**
- * Returns a parsed fog object
+ * Parses a prop value as generic array type.
+ *
+ * @param {string|*[]} array - Prop value.
+ * @return {*[]} Parsed array.
  */
-export function parseFog(str) {
-  return str.isFog ? str : new Fog(...str.trim().split(/\s+/).map((elm, i) => (i === 0 ? elm : parseFloat(elm))));
+export function parseArray(array) {
+  return Array.isArray(array) ? array : array.split(',');
 }
 
 /**
- * Returns a parsed Color object
+ * Parses a prop value as vector2array type.
+ *
+ * @param {string|(string|Vector2)[]} array - Prop value.
+ * @return {Vector2[]} Parsed array of THREE.Vector2 instances.
  */
-export function parseColor(str) {
-  return str.isColor ? str : new Color(str);
+export function parseVector2Array(array) {
+  const isArray = Array.isArray(array);
+  if (isArray && array.every((v) => v.isVector2)) return array;
+  return (isArray ? array : array.split(',')).map(parseVector2);
 }
 
 /**
- * Return a parsed name array
+ * Returns a parsed fog object
  */
-export function parseNames(str) {
-  return Array.isArray(str) ? str : str.split(' ');
+export function parseFog(str) {
+  return str.isFog ? str : new Fog(...str.trim().split(/\s+/).map((elm, i) => (i === 0 ? elm : parseFloat(elm))));
 }
diff --git a/src/renderers/vgl-renderer.js b/src/renderers/vgl-renderer.js
index 5cb2a86..abe1840 100644
--- a/src/renderers/vgl-renderer.js
+++ b/src/renderers/vgl-renderer.js
@@ -1,7 +1,7 @@
 import { WebGLRenderer } from 'three';
 import VglNamespace from '../core/vgl-namespace';
 import { boolean, string, name } from '../types';
-import { nameValidator } from '../validators';
+import { validateName } from '../validators';
 import { setCameraSize } from './utilities';
 
 /**
@@ -14,8 +14,10 @@ import { setCameraSize } from './utilities';
 export default {
   mixins: [VglNamespace],
   props: {
-    /** Shader precision. Can be "highp", "mediump" or "lowp". */
-    precision: string,
+    /** Name of the using camera. */
+    camera: { type: name, required: true, validator: validateName },
+    /** Name of the target scene. */
+    scene: { type: name, required: true, validator: validateName },
     /** Whether the canvas contains an alpha (transparency) buffer or not. */
     alpha: boolean,
     /** Whether the renderer will assume that colors have premultiplied alpha. */
@@ -24,23 +26,27 @@ export default {
     antialias: boolean,
     /** Whether the drawing buffer has a stencil buffer of at least 8 bits. */
     disableStencil: boolean,
-    /**
-     * A hint to the user agent indicating what configuration of GPU is suitable
-     * for this WebGL context. Can be "high-performance", "low-power" or "default".
-     */
-    powerPreference: string,
     /** Whether to preserve the buffers until manually cleared or overwritten. */
     preserveDrawingBuffer: boolean,
     /** Whether the drawing buffer has a depth buffer of at least 16 bits. */
     disableDepth: boolean,
     /** Whether to use a logarithmic depth buffer. */
     logarithmicDepthBuffer: boolean,
-    /** Name of the using camera. */
-    camera: { type: name, validator: nameValidator },
-    /** Name of the target scene. */
-    scene: { type: name, validator: nameValidator },
     /** If set, use shadow maps in the scene. */
     shadowMapEnabled: boolean,
+    /** Shader precision. Can be "highp", "mediump" or "lowp". */
+    precision: {
+      type: string,
+      validator: (v) => /^(highp|mediump|lowp)$/.test(v),
+    },
+    /**
+     * A hint to the user agent indicating what configuration of GPU is suitable
+     * for this WebGL context. Can be "high-performance", "low-power" or "default".
+     */
+    powerPreference: {
+      type: string,
+      validator: (v) => /^(high-performance|low-power|default)$/.test(v),
+    },
   },
   computed: {
     /** The THREE.WebGLRenderer instance. */
diff --git a/src/scenes/vgl-scene.js b/src/scenes/vgl-scene.js
index b57326f..dc3869d 100644
--- a/src/scenes/vgl-scene.js
+++ b/src/scenes/vgl-scene.js
@@ -1,7 +1,8 @@
 import { Scene } from 'three';
 import VglObject3d from '../core/vgl-object3d';
 import { parseFog, parseColor } from '../parsers';
-import { string, fog } from '../types';
+import { string, fog, name } from '../types';
+import { validateName } from '../validators';
 
 /**
  * This is where you place objects,
@@ -21,7 +22,9 @@ export default {
     */
     backgroundColor: string,
     /** Expecting to accept a string representing a texture name. */
-    backgroundTexture: string,
+    backgroundTexture: { type: name, validator: validateName },
+    /** Name of the scene. */
+    name: { type: name, required: true, validator: validateName },
   },
   computed: {
     /** The THREE.Scene instance. */
@@ -60,9 +63,9 @@ export default {
       },
       immediate: true,
     },
-    name(name, oldName) {
+    name(newName, oldName) {
       this.vglNamespace.scenes.delete(oldName, this.inst);
-      this.vglNamespace.scenes.set(name, this.inst);
+      this.vglNamespace.scenes.set(newName, this.inst);
     },
     fog(newFog) {
       this.inst.fog = parseFog(newFog);
@@ -73,13 +76,13 @@ export default {
       this.vglObject3d.emit();
     },
     backgroundTexture: {
-      handler(name, oldName) {
+      handler(newName, oldName) {
         if (oldName !== undefined) {
           this.vglNamespace.textures.unlisten(oldName, this.setBackgroundTexture);
         }
-        if (name !== undefined) {
-          this.vglNamespace.textures.listen(name, this.setBackgroundTexture);
-          this.setBackgroundTexture(this.vglNamespace.textures.get(name));
+        if (newName !== undefined) {
+          this.vglNamespace.textures.listen(newName, this.setBackgroundTexture);
+          this.setBackgroundTexture(this.vglNamespace.textures.get(newName));
         }
       },
       immediate: true,
diff --git a/src/textures/vgl-texture.js b/src/textures/vgl-texture.js
index d8d3aaa..f6b3a08 100644
--- a/src/textures/vgl-texture.js
+++ b/src/textures/vgl-texture.js
@@ -1,58 +1,21 @@
 import {
-  TextureLoader,
-  UVMapping,
-  CubeReflectionMapping,
-  CubeRefractionMapping,
-  EquirectangularReflectionMapping,
-  EquirectangularRefractionMapping,
-  SphericalReflectionMapping,
-  CubeUVReflectionMapping,
-  CubeUVRefractionMapping,
-  RepeatWrapping,
-  ClampToEdgeWrapping,
-  MirroredRepeatWrapping,
-  NearestFilter,
-  LinearFilter,
-  NearestMipMapNearestFilter,
-  NearestMipMapLinearFilter,
-  LinearMipMapNearestFilter,
-  LinearMipMapLinearFilter,
-  AlphaFormat,
-  RGBFormat,
-  RGBAFormat,
-  LuminanceFormat,
-  LuminanceAlphaFormat,
-  RGBEFormat,
-  DepthFormat,
-  DepthStencilFormat,
-  UnsignedByteType,
-  ByteType,
-  ShortType,
-  UnsignedShortType,
-  IntType,
-  UnsignedIntType,
-  FloatType,
-  HalfFloatType,
-  UnsignedShort4444Type,
-  UnsignedShort5551Type,
-  UnsignedShort565Type,
-  UnsignedInt248Type,
-  LinearEncoding,
-  sRGBEncoding,
-  GammaEncoding,
-  RGBEEncoding,
-  LogLuvEncoding,
-  RGBM7Encoding,
-  RGBM16Encoding,
-  RGBDEncoding,
-  BasicDepthPacking,
+  TextureLoader, UVMapping, CubeReflectionMapping, CubeRefractionMapping,
+  EquirectangularReflectionMapping, EquirectangularRefractionMapping, SphericalReflectionMapping,
+  CubeUVReflectionMapping, CubeUVRefractionMapping, RepeatWrapping, ClampToEdgeWrapping,
+  MirroredRepeatWrapping, NearestFilter, LinearFilter, NearestMipMapNearestFilter,
+  NearestMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipMapLinearFilter, AlphaFormat,
+  RGBFormat, RGBAFormat, LuminanceFormat, LuminanceAlphaFormat, RGBEFormat, DepthFormat,
+  DepthStencilFormat, UnsignedByteType, ByteType, ShortType, UnsignedShortType, IntType,
+  UnsignedIntType, FloatType, HalfFloatType, UnsignedShort4444Type, UnsignedShort5551Type,
+  UnsignedShort565Type, UnsignedInt248Type, LinearEncoding, sRGBEncoding, GammaEncoding,
+  RGBEEncoding, LogLuvEncoding, RGBM7Encoding, RGBM16Encoding, RGBDEncoding, BasicDepthPacking,
   RGBADepthPacking,
 } from 'three';
 import {
-  string, number, vector2, boolean, name,
+  string, vector2, boolean, name, int, float,
 } from '../types';
 import { parseVector2 } from '../parsers';
-import { nameValidator } from '../validators';
+import { validateName, validateVector2 } from '../validators';
 
 const mapping = {
   uv: UVMapping,
@@ -133,21 +96,21 @@ export default {
   props: {
     /** The path or URL to the file. This can also be a Data URI. */
     src: string,
-    name: { type: name, validator: nameValidator },
+    name: { type: name, required: true, validator: validateName },
     mapping: { type: string, default: 'uv' },
     wrapS: { type: string, default: 'clamp-to-edge' },
     wrapT: { type: string, default: 'clamp-to-edge' },
     magFilter: { type: string, default: 'linear' },
     minFilter: { type: string, default: 'linear-mip-map-linear' },
-    anisotropy: { type: number, default: 1 },
+    anisotropy: { type: int, default: 1 },
     format: string,
     type: { type: string, default: 'unsigned-byte' },
-    offset: vector2,
-    repeat: vector2,
-    rotation: { type: number, default: 0 },
-    center: vector2,
+    offset: { type: vector2, validator: validateVector2 },
+    repeat: { type: vector2, validator: validateVector2 },
+    rotation: { type: float, default: 0 },
+    center: { type: vector2, validator: validateVector2 },
     premultiplyAlpha: boolean,
-    unpackAlignment: { type: number, default: 4 },
+    unpackAlignment: { type: int, default: 4 },
     encoding: { type: string, default: 'linear' },
   },
   computed: {
diff --git a/src/types.js b/src/types.js
index eb3dec2..e3df3eb 100644
--- a/src/types.js
+++ b/src/types.js
@@ -1,22 +1,19 @@
 import {
-  Vector3,
-  Spherical,
-  Euler,
-  Vector2,
-  Quaternion,
-  Fog,
+  Vector2, Vector3, Euler, Quaternion, Spherical, Color, Fog,
 } from 'three';
 
-export const number = [String, Number];
+export const boolean = Boolean;
+export const int = [String, Number];
+export const float = [String, Number];
 export const string = String;
+export const name = String;
+export const names = [String, Array];
+export const color = [String, Color, Number];
+export const vector2 = [String, Vector2];
 export const vector3 = [String, Vector3];
-export const spherical = [String, Spherical];
-export const boolean = Boolean;
 export const euler = [String, Euler];
-export const vector2 = [String, Vector2];
 export const quaternion = [String, Quaternion];
+export const spherical = [String, Spherical];
 export const floatArray = [String, Array];
 export const vector2Array = [String, Array];
 export const fog = [String, Fog];
-export const name = String;
-export const names = [String, Array];
diff --git a/src/validators.js b/src/validators.js
index ea84bfd..ca034c7 100644
--- a/src/validators.js
+++ b/src/validators.js
@@ -1,7 +1,107 @@
-export function nameValidator(value) {
-  return value.length > 0 && !value.includes(' ');
+import {
+  Vector3, Vector2, Euler, Quaternion, Spherical,
+} from 'three';
+
+function isFloat(value) {
+  return !Number.isNaN(parseFloat(value));
+}
+
+/**
+ * Validates a name type prop.
+ *
+ * @param {string} name - Prop value.
+ * @return {boolean} Whether value is valid or not.
+ */
+export function validateName(name) {
+  return /^\s*\S+\s*$/.test(name);
+}
+
+/**
+ * Validates a names type prop.
+ *
+ * @param {string|string[]} names - Prop value.
+ * @return {boolean} Whether value is valid or not.
+ */
+export function validateNames(names) {
+  return Array.isArray(names) ? names.every(validateName) : /\S+/.test(names);
+}
+
+/**
+ * Validates a vector2 type prop.
+ *
+ * @param  {string|(string|number)[]|Vector2} vector - The prop value.
+ * @return {boolean} Whether value is valid or not.
+ */
+export function validateVector2(vector) {
+  if (vector instanceof Vector2) return true;
+  const v = Array.isArray(vector) ? vector : vector.trim().split(/\s+/);
+  return v.length === 2 && v.every(isFloat);
+}
+
+/**
+ * Validates a vector3 type prop.
+ *
+ * @param  {string|(string|number)[]|Vector3} vector - The prop value.
+ * @return {boolean} Whether value is valid or not.
+ */
+export function validateVector3(vector) {
+  if (vector instanceof Vector3) return true;
+  const v = Array.isArray(vector) ? vector : vector.trim().split(/\s+/);
+  return v.length === 3 && v.every(isFloat);
+}
+
+/**
+ * Validates a euler type prop.
+ *
+ * @param  {string|(string|number)[]|Euler} euler - The prop value.
+ * @return {boolean} Whether value is valid or not.
+ */
+export function validateEuler(euler) {
+  if (euler instanceof Euler) return true;
+  const v = Array.isArray(euler) ? euler : euler.trim().split(/\s+/);
+  return v.length === 4 && v.slice(0, 3).every(isFloat) && /[XYZ]{3}/.test(v[3]);
+}
+
+/**
+ * Validates a quaternion type prop.
+ *
+ * @param  {string|(string|number)[]|Quaternion} quaternion - The prop value.
+ * @return {boolean} Whether value is valid or not.
+ */
+export function validateQuaternion(quaternion) {
+  if (quaternion instanceof Quaternion) return true;
+  const q = Array.isArray(quaternion) ? quaternion : quaternion.trim().split(/\s+/);
+  return q.length === 4 && q.every(isFloat);
+}
+
+/**
+ * Validates a spherical type prop.
+ *
+ * @param  {string|(string|number)[]|Spherical} spherical - The prop value.
+ * @return {boolean} Whether value is valid or not.
+ */
+export function validateSpherical(spherical) {
+  if (spherical instanceof Spherical) return true;
+  const s = Array.isArray(spherical) ? spherical : spherical.trim().split(/\s+/);
+  return s.length === 3 && s.every(isFloat);
+}
+
+/**
+ * Validates a floatArray type prop.
+ *
+ * @param {string|(string|number)[]} array - The prop value.
+ * @return {boolean} Wheter value is valid or not.
+ */
+export function validateFloatArray(array) {
+  return (Array.isArray(array) ? array : array.split(',')).every(isFloat);
 }
 
-export function namesValidator(value) {
-  return Array.isArray(value) ? value.every((n) => nameValidator(n)) : value.length > 0;
+/**
+ * Validates a vector2Array type prop.
+ *
+ * @param {string|(string|Vector2)[]} array - The prop value.
+ * @return {boolean} Wheter value is valid or not.
+ */
+export function validateVector2Array(array) {
+  return (Array.isArray(array) ? array : array.split(',')).every(validateVector2);
 }


Test patch:
diff --git a/test/parsers.spec.js b/test/parsers.spec.js
new file mode 100644
index 0000000..3864da8
--- /dev/null
+++ b/test/parsers.spec.js
@@ -0,0 +1,261 @@
+import {
+  Color, Vector2, Vector3, Euler, Quaternion, Spherical,
+} from 'three';
+import {
+  parseNames, parseColor, parseVector2, parseVector3, parseEuler, parseQuaternion, parseSpherical,
+  parseVector2Array,
+} from '../src/parsers';
+
+describe('Parser functions', () => {
+  describe('parseNames()', () => {
+    test('should parse a space separated string', () => {
+      expect(parseNames('abc123 bcd!"#')).toEqual(['abc123', 'bcd!"#']);
+    });
+    test('should parse a string separated by multi spaces', () => {
+      expect(parseNames('abc123    bcd!"#')).toEqual(['abc123', 'bcd!"#']);
+    });
+    test('should parse a string with leading and trailing spaces', () => {
+      expect(parseNames('  abc123 bcd!"# ')).toEqual(['abc123', 'bcd!"#']);
+    });
+    test('should return original array', () => {
+      const names = ['abc123', 'bcd!"#'];
+      expect(parseNames(names)).toBe(names);
+    });
+  });
+  describe('parseColor()', () => {
+    test('should parse a CSS style color', () => {
+      const parsed = parseColor('#4f3ed5');
+      expect(parsed).toBeInstanceOf(Color);
+      expect(parsed.getHex()).toBe(0x4f3ed5);
+    });
+    test('should parse a hexadecimal color', () => {
+      const parsed = parseColor(0x4f3ed5);
+      expect(parsed).toBeInstanceOf(Color);
+      expect(parsed.getHex()).toBe(0x4f3ed5);
+    });
+    test('should return original Color instance', () => {
+      const color = new Color(0x4f3ed5);
+      expect(parseColor(color)).toBe(color);
+    });
+  });
+  describe('parseVector2()', () => {
+    test('should parse a space separated string', () => {
+      const parsed = parseVector2('12.3 23.4');
+      expect(parsed).toBeInstanceOf(Vector2);
+      expect(parsed).toHaveProperty('x', 12.3);
+      expect(parsed).toHaveProperty('y', 23.4);
+    });
+    test('should parse a space separated string with leading and trailing spaces', () => {
+      const parsed = parseVector2(' 12.3 23.4   ');
+      expect(parsed).toBeInstanceOf(Vector2);
+      expect(parsed).toHaveProperty('x', 12.3);
+      expect(parsed).toHaveProperty('y', 23.4);
+    });
+    test('should parse an array contains strings', () => {
+      const parsed = parseVector2(['12.3', '23.4']);
+      expect(parsed).toBeInstanceOf(Vector2);
+      expect(parsed).toHaveProperty('x', 12.3);
+      expect(parsed).toHaveProperty('y', 23.4);
+    });
+    test('should parse an array contains numbers', () => {
+      const parsed = parseVector2([12.3, 23.4]);
+      expect(parsed).toBeInstanceOf(Vector2);
+      expect(parsed).toHaveProperty('x', 12.3);
+      expect(parsed).toHaveProperty('y', 23.4);
+    });
+    test('should return original Vector2 instance', () => {
+      const vector = new Vector2(12.3, 23.4);
+      expect(parseVector2(vector)).toBe(vector);
+    });
+  });
+  describe('parseVector3()', () => {
+    test('should parse a space separated string', () => {
+      const parsed = parseVector3('12.3 23.4 45.6');
+      expect(parsed).toBeInstanceOf(Vector3);
+      expect(parsed).toHaveProperty('x', 12.3);
+      expect(parsed).toHaveProperty('y', 23.4);
+      expect(parsed).toHaveProperty('z', 45.6);
+    });
+    test('should parse a space separated string with leading and trailing spaces', () => {
+      const parsed = parseVector3(' 12.3 23.4  45.6  ');
+      expect(parsed).toBeInstanceOf(Vector3);
+      expect(parsed).toHaveProperty('x', 12.3);
+      expect(parsed).toHaveProperty('y', 23.4);
+      expect(parsed).toHaveProperty('z', 45.6);
+    });
+    test('should parse an array contains strings', () => {
+      const parsed = parseVector3(['12.3', '23.4', '45.6']);
+      expect(parsed).toBeInstanceOf(Vector3);
+      expect(parsed).toHaveProperty('x', 12.3);
+      expect(parsed).toHaveProperty('y', 23.4);
+      expect(parsed).toHaveProperty('z', 45.6);
+    });
+    test('should parse an array contains numbers', () => {
+      const parsed = parseVector3([12.3, 23.4, 45.6]);
+      expect(parsed).toBeInstanceOf(Vector3);
+      expect(parsed).toHaveProperty('x', 12.3);
+      expect(parsed).toHaveProperty('y', 23.4);
+      expect(parsed).toHaveProperty('z', 45.6);
+    });
+    test('should return original Vector3 instance', () => {
+      const vector = new Vector3(12.3, 23.4, 45.6);
+      expect(parseVector3(vector)).toBe(vector);
+    });
+  });
+  describe('parseEuler()', () => {
+    test('should parse a space separated string', () => {
+      const parsed = parseEuler('12.3 23.4 45.6 YXZ');
+      expect(parsed).toBeInstanceOf(Euler);
+      expect(parsed).toHaveProperty('x', 12.3);
+      expect(parsed).toHaveProperty('y', 23.4);
+      expect(parsed).toHaveProperty('z', 45.6);
+      expect(parsed).toHaveProperty('order', 'YXZ');
+    });
+    test('should parse a space separated string with leading and trailing spaces', () => {
+      const parsed = parseEuler(' 12.3 23.4  45.6  YXZ   ');
+      expect(parsed).toBeInstanceOf(Euler);
+      expect(parsed).toHaveProperty('x', 12.3);
+      expect(parsed).toHaveProperty('y', 23.4);
+      expect(parsed).toHaveProperty('z', 45.6);
+      expect(parsed).toHaveProperty('order', 'YXZ');
+    });
+    test('should parse an array contains strings', () => {
+      const parsed = parseEuler(['12.3', '23.4', '45.6', 'YXZ']);
+      expect(parsed).toBeInstanceOf(Euler);
+      expect(parsed).toHaveProperty('x', 12.3);
+      expect(parsed).toHaveProperty('y', 23.4);
+      expect(parsed).toHaveProperty('z', 45.6);
+      expect(parsed).toHaveProperty('order', 'YXZ');
+    });
+    test('should parse an array contains numbers', () => {
+      const parsed = parseEuler([12.3, 23.4, 45.6, 'YXZ']);
+      expect(parsed).toBeInstanceOf(Euler);
+      expect(parsed).toHaveProperty('x', 12.3);
+      expect(parsed).toHaveProperty('y', 23.4);
+      expect(parsed).toHaveProperty('z', 45.6);
+      expect(parsed).toHaveProperty('order', 'YXZ');
+    });
+    test('should return original Euler instance', () => {
+      const euler = new Euler(12.3, 23.4, 45.6, 'YXZ');
+      expect(parseEuler(euler)).toBe(euler);
+    });
+  });
+  describe('parseQuaternion()', () => {
+    test('should parse a space separated string', () => {
+      const parsed = parseQuaternion('0.312 0.903 0.296 0.32');
+      expect(parsed).toBeInstanceOf(Quaternion);
+      expect(parsed).toHaveProperty('x', 0.312);
+      expect(parsed).toHaveProperty('y', 0.903);
+      expect(parsed).toHaveProperty('z', 0.296);
+      expect(parsed).toHaveProperty('w', 0.32);
+    });
+    test('should parse a space separated string with leading and trailing spaces', () => {
+      const parsed = parseQuaternion(' 0.312  0.903 0.296   0.32   ');
+      expect(parsed).toBeInstanceOf(Quaternion);
+      expect(parsed).toHaveProperty('x', 0.312);
+      expect(parsed).toHaveProperty('y', 0.903);
+      expect(parsed).toHaveProperty('z', 0.296);
+      expect(parsed).toHaveProperty('w', 0.32);
+    });
+    test('should parse an array contains strings', () => {
+      const parsed = parseQuaternion(['0.312', '0.903', '0.296', '0.32']);
+      expect(parsed).toBeInstanceOf(Quaternion);
+      expect(parsed).toHaveProperty('x', 0.312);
+      expect(parsed).toHaveProperty('y', 0.903);
+      expect(parsed).toHaveProperty('z', 0.296);
+      expect(parsed).toHaveProperty('w', 0.32);
+    });
+    test('should parse an array contains numbers', () => {
+      const parsed = parseQuaternion([0.312, 0.903, 0.296, 0.32]);
+      expect(parsed).toBeInstanceOf(Quaternion);
+      expect(parsed).toHaveProperty('x', 0.312);
+      expect(parsed).toHaveProperty('y', 0.903);
+      expect(parsed).toHaveProperty('z', 0.296);
+      expect(parsed).toHaveProperty('w', 0.32);
+    });
+    test('should return original Quaternion instance', () => {
+      const quaternion = new Quaternion(0.312, 0.903, 0.296, 0.32);
+      expect(parseQuaternion(quaternion)).toBe(quaternion);
+    });
+  });
+  describe('parseSpherical()', () => {
+    test('should parse a space separated string', () => {
+      const parsed = parseSpherical('31.2 0.903 0.296');
+      expect(parsed).toBeInstanceOf(Spherical);
+      expect(parsed).toHaveProperty('radius', 31.2);
+      expect(parsed).toHaveProperty('phi', 0.903);
+      expect(parsed).toHaveProperty('theta', 0.296);
+    });
+    test('should parse a space separated string with leading and trailing spaces', () => {
+      const parsed = parseSpherical(' 31.2  0.903 0.296   ');
+      expect(parsed).toBeInstanceOf(Spherical);
+      expect(parsed).toHaveProperty('radius', 31.2);
+      expect(parsed).toHaveProperty('phi', 0.903);
+      expect(parsed).toHaveProperty('theta', 0.296);
+    });
+    test('should parse an array contains strings', () => {
+      const parsed = parseSpherical(['31.2', '0.903', '0.296']);
+      expect(parsed).toBeInstanceOf(Spherical);
+      expect(parsed).toHaveProperty('radius', 31.2);
+      expect(parsed).toHaveProperty('phi', 0.903);
+      expect(parsed).toHaveProperty('theta', 0.296);
+    });
+    test('should parse an array contains numbers', () => {
+      const parsed = parseSpherical([31.2, 0.903, 0.296]);
+      expect(parsed).toBeInstanceOf(Spherical);
+      expect(parsed).toHaveProperty('radius', 31.2);
+      expect(parsed).toHaveProperty('phi', 0.903);
+      expect(parsed).toHaveProperty('theta', 0.296);
+    });
+    test('should return original Spherical instance', () => {
+      const spherical = new Spherical(31.2, 0.903, 0.296);
+      expect(parseSpherical(spherical)).toBe(spherical);
+    });
+  });
+  describe('parseVector2Array()', () => {
+    test('should parse a space separated string', () => {
+      const parsed = parseVector2Array('31.2 45.6, 12.3 67.8');
+      expect(parsed).toEqual([expect.any(Vector2), expect.any(Vector2)]);
+      expect(parsed[0]).toHaveProperty('x', 31.2);
+      expect(parsed[0]).toHaveProperty('y', 45.6);
+      expect(parsed[1]).toHaveProperty('x', 12.3);
+      expect(parsed[1]).toHaveProperty('y', 67.8);
+    });
+    test('should parse a space separated string with leading and trailing spaces', () => {
+      const parsed = parseVector2Array(' 31.2  45.6 ,12.3   67.8   ');
+      expect(parsed).toEqual([expect.any(Vector2), expect.any(Vector2)]);
+      expect(parsed[0]).toHaveProperty('x', 31.2);
+      expect(parsed[0]).toHaveProperty('y', 45.6);
+      expect(parsed[1]).toHaveProperty('x', 12.3);
+      expect(parsed[1]).toHaveProperty('y', 67.8);
+    });
+    test('should parse an array contains strings', () => {
+      const parsed = parseVector2Array(['31.2 45.6', '12.3 67.8']);
+      expect(parsed).toEqual([expect.any(Vector2), expect.any(Vector2)]);
+      expect(parsed[0]).toHaveProperty('x', 31.2);
+      expect(parsed[0]).toHaveProperty('y', 45.6);
+      expect(parsed[1]).toHaveProperty('x', 12.3);
+      expect(parsed[1]).toHaveProperty('y', 67.8);
+    });
+    test('should parse an array contains string arrays', () => {
+      const parsed = parseVector2Array([['31.2', '45.6'], ['12.3', '67.8']]);
+      expect(parsed).toEqual([expect.any(Vector2), expect.any(Vector2)]);
+      expect(parsed[0]).toHaveProperty('x', 31.2);
+      expect(parsed[0]).toHaveProperty('y', 45.6);
+      expect(parsed[1]).toHaveProperty('x', 12.3);
+      expect(parsed[1]).toHaveProperty('y', 67.8);
+    });
+    test('should parse an array contains number arrays', () => {
+      const parsed = parseVector2Array([[31.2, 45.6], [12.3, 67.8]]);
+      expect(parsed).toEqual([expect.any(Vector2), expect.any(Vector2)]);
+      expect(parsed[0]).toHaveProperty('x', 31.2);
+      expect(parsed[0]).toHaveProperty('y', 45.6);
+      expect(parsed[1]).toHaveProperty('x', 12.3);
+      expect(parsed[1]).toHaveProperty('y', 67.8);
+    });
+    test('should return original array of Vector2 instances', () => {
+      const array = [new Vector2(31.2, 45.6), new Vector2(12.3, 67.8)];
+      expect(parseVector2Array(array)).toBe(array);
+    });
+  });
+});
diff --git a/test/validators.spec.js b/test/validators.spec.js
new file mode 100644
index 0000000..e2b3eb1
--- /dev/null
+++ b/test/validators.spec.js
@@ -0,0 +1,301 @@
+import {
+  Vector3, Vector2, Euler, Quaternion, Spherical,
+} from 'three';
+import {
+  validateName, validateNames, validateVector3, validateVector2, validateEuler, validateQuaternion,
+  validateSpherical, validateFloatArray, validateVector2Array,
+} from '../src/validators';
+
+describe('Validator functions', () => {
+  describe('validateName()', () => {
+    test('should return true for valid name', () => {
+      expect(validateName('Valid_name')).toBe(true);
+    });
+    test('should return true for valid name with leading and trailing spaces', () => {
+      expect(validateName('   valid-name ')).toBe(true);
+    });
+    test('should return false for name including spaces', () => {
+      expect(validateName('invalid name')).toBe(false);
+    });
+    test('should return false for name including spaces wirh leading and trailing spaces', () => {
+      expect(validateName(' invalid name   ')).toBe(false);
+    });
+    test('should return false for an empty name', () => {
+      expect(validateName('')).toBe(false);
+    });
+    test('should return false for space only string', () => {
+      expect(validateName('   ')).toBe(false);
+    });
+  });
+  describe('validateNames()', () => {
+    test('should return true for space separated names', () => {
+      expect(validateNames('valid_name1 valid_name2  valid-name-3 ')).toBe(true);
+    });
+    test('should return true for a name without spaces', () => {
+      expect(validateNames('valid_name')).toBe(true);
+    });
+    test('should return true for an array of valid names', () => {
+      expect(validateNames(['valid_name1', 'valid_name2', 'valid-name-3'])).toBe(true);
+    });
+    test('should return false for an empty string', () => {
+      expect(validateNames('')).toBe(false);
+    });
+    test('should return false for space only string', () => {
+      expect(validateNames('   ')).toBe(false);
+    });
+    test('should return false for an array containing invalid names', () => {
+      expect(validateNames(['invalid name1', 'valid_name2', 'valid-name-3'])).toBe(false);
+    });
+  });
+  describe('validateVector2()', () => {
+    test('should return true for space separated coodinates', () => {
+      expect(validateVector2('1.1 2.1')).toBe(true);
+    });
+    test('should return true for space separated coodinates with leading/trailing spaces', () => {
+      expect(validateVector2('  1.1  2.1  ')).toBe(true);
+    });
+    test('should return true for an array of parsable strings', () => {
+      expect(validateVector2(['1.1', '2.1'])).toBe(true);
+    });
+    test('should return true for an array of numbers', () => {
+      expect(validateVector2([1.1, 2.1])).toBe(true);
+    });
+    test('should return true for a Vector2 instance', () => {
+      expect(validateVector2(new Vector2(1.1, 2.1))).toBe(true);
+    });
+    test('should return false for a string contains too many coodinates', () => {
+      expect(validateVector2('1.1 2.1 3.1')).toBe(false);
+    });
+    test('should return false for a string contains too less coodinates', () => {
+      expect(validateVector2('1.1')).toBe(false);
+    });
+    test('should return false for an array contains too many coodinate string', () => {
+      expect(validateVector2(['1.1', '2.1', '3.1'])).toBe(false);
+    });
+    test('should return false for an array contains too many coodinate number', () => {
+      expect(validateVector2([1.1, 2.1, 3.1])).toBe(false);
+    });
+    test('should return false for an array contains too less coodinate string', () => {
+      expect(validateVector2(['1.1'])).toBe(false);
+    });
+    test('should return false for an array contains too less coodinate number', () => {
+      expect(validateVector2([1.1])).toBe(false);
+    });
+    test('should return false for a string contains non-parsable coodinates', () => {
+      expect(validateVector2('1.1 abc')).toBe(false);
+    });
+    test('should return false for an array contains non-parsable coodinate string', () => {
+      expect(validateVector2(['1.1', 'abc'])).toBe(false);
+    });
+  });
+  describe('validateVector3()', () => {
+    test('should return true for space separated coodinates', () => {
+      expect(validateVector3('1.1 2.1 3.1')).toBe(true);
+    });
+    test('should return true for space separated coodinates with leading/trailing spaces', () => {
+      expect(validateVector3('  1.1  2.1 3.1 ')).toBe(true);
+    });
+    test('should return true for an array of parsable strings', () => {
+      expect(validateVector3(['1.1', '2.1', '3.1'])).toBe(true);
+    });
+    test('should return true for an array of numbers', () => {
+      expect(validateVector3([1.1, 2.1, 3.1])).toBe(true);
+    });
+    test('should return true for a Vector3 instance', () => {
+      expect(validateVector3(new Vector3(1.1, 2.1, 3.1))).toBe(true);
+    });
+    test('should return false for a string contains too many coodinates', () => {
+      expect(validateVector3('1.1 2.1 3.1 4.1')).toBe(false);
+    });
+    test('should return false for a string contains too less coodinates', () => {
+      expect(validateVector3('1.1 2.1')).toBe(false);
+    });
+    test('should return false for an array contains too many coodinate string', () => {
+      expect(validateVector3(['1.1', '2.1', '3.1', '4.1'])).toBe(false);
+    });
+    test('should return false for an array contains too many coodinate number', () => {
+      expect(validateVector3([1.1, 2.1, 3.1, 4.1])).toBe(false);
+    });
+    test('should return false for an array contains too less coodinate string', () => {
+      expect(validateVector3(['1.1', '2.1'])).toBe(false);
+    });
+    test('should return false for an array contains too less coodinate number', () => {
+      expect(validateVector3([1.1, 2.1])).toBe(false);
+    });
+    test('should return false for a string contains non-parsable coodinates', () => {
+      expect(validateVector3('1.1 abc 4.1')).toBe(false);
+    });
+    test('should return false for an array contains non-parsable coodinate string', () => {
+      expect(validateVector3(['1.1', 'abc', '4.1'])).toBe(false);
+    });
+  });
+  describe('validateEuler()', () => {
+    test('should return true for space separated coodinates', () => {
+      expect(validateEuler('1.1 2.1 3.1 YXZ')).toBe(true);
+    });
+    test('should return true for space separated coodinates with leading/trailing spaces', () => {
+      expect(validateEuler('  1.1  2.1 3.1  YXZ ')).toBe(true);
+    });
+    test('should return true for an array of parsable strings', () => {
+      expect(validateEuler(['1.1', '2.1', '3.1', 'YXZ'])).toBe(true);
+    });
+    test('should return true for an array of numbers and order string', () => {
+      expect(validateEuler([1.1, 2.1, 3.1, 'YXZ'])).toBe(true);
+    });
+    test('should return true for a Euler instance', () => {
+      expect(validateEuler(new Euler(1.1, 2.1, 3.1, 'YXZ'))).toBe(true);
+    });
+    test('should return false for a string contains too many coodinates', () => {
+      expect(validateEuler('1.1 2.1 3.1 4.1 YXZ')).toBe(false);
+    });
+    test('should return false for a string contains too less coodinates', () => {
+      expect(validateEuler('1.1 2.1 YXZ')).toBe(false);
+    });
+    test('should return false for an array contains too many coodinate string', () => {
+      expect(validateEuler(['1.1', '2.1', '3.1', '4.1', 'YXZ'])).toBe(false);
+    });
+    test('should return false for an array contains too many coodinate number', () => {
+      expect(validateEuler([1.1, 2.1, 3.1, 4.1, 'YXZ'])).toBe(false);
+    });
+    test('should return false for an array contains too less coodinate string', () => {
+      expect(validateEuler(['1.1', '2.1', 'YXZ'])).toBe(false);
+    });
+    test('should return false for an array contains too less coodinate number', () => {
+      expect(validateEuler([1.1, 2.1, 'YXZ'])).toBe(false);
+    });
+    test('should return false for a string contains non-parsable coodinates', () => {
+      expect(validateEuler('1.1 abc 4.1 YXZ')).toBe(false);
+    });
+    test('should return false for a string with invalid order string', () => {
+      expect(validateEuler('1.1 2.1 4.1 YXA')).toBe(false);
+    });
+    test('should return false for an array contains non-parsable coodinate string', () => {
+      expect(validateEuler(['1.1', 'abc', '4.1', 'YXZ'])).toBe(false);
+    });
+    test('should return false for an array with invalid order string', () => {
+      expect(validateEuler('1.1', '2.1', '4.1', 'YXA')).toBe(false);
+    });
+  });
+  describe('validateQuaternion()', () => {
+    test('should return true for space separated coodinates', () => {
+      expect(validateQuaternion('0.5 0.5 0.71 0.35')).toBe(true);
+    });
+    test('should return true for space separated coodinates with leading/trailing spaces', () => {
+      expect(validateQuaternion('  0.5  0.5 0.71 0.35 ')).toBe(true);
+    });
+    test('should return true for an array of parsable strings', () => {
+      expect(validateQuaternion(['0.5', '0.5', '0.71', '0.35'])).toBe(true);
+    });
+    test('should return true for an array of numbers', () => {
+      expect(validateQuaternion([0.5, 0.5, 0.71, 0.35])).toBe(true);
+    });
+    test('should return true for a Quaternion instance', () => {
+      expect(validateQuaternion(new Quaternion(0.5, 0.5, 0.71, 0.35))).toBe(true);
+    });
+    test('should return false for a string contains too many coodinates', () => {
+      expect(validateQuaternion('0.5 0.5 0.71 0.35 0.24')).toBe(false);
+    });
+    test('should return false for a string contains too less coodinates', () => {
+      expect(validateQuaternion('0.5 0.5 0.71')).toBe(false);
+    });
+    test('should return false for an array contains too many coodinate string', () => {
+      expect(validateQuaternion(['0.5', '0.5', '0.71', '0.35', '0.24'])).toBe(false);
+    });
+    test('should return false for an array contains too many coodinate number', () => {
+      expect(validateQuaternion([0.5, 0.5, 0.71, 0.35, 0.24])).toBe(false);
+    });
+    test('should return false for an array contains too less coodinate string', () => {
+      expect(validateQuaternion(['0.5', '0.5', '0.71'])).toBe(false);
+    });
+    test('should return false for an array contains too less coodinate number', () => {
+      expect(validateQuaternion([0.5, 0.5, 0.71])).toBe(false);
+    });
+    test('should return false for a string contains non-parsable coodinates', () => {
+      expect(validateQuaternion('0.5 0.5 abc 0.35')).toBe(false);
+    });
+    test('should return false for an array contains non-parsable coodinate string', () => {
+      expect(validateQuaternion(['0.5', '0.5', 'abc', '0.35'])).toBe(false);
+    });
+  });
+  describe('validateSpherical()', () => {
+    test('should return true for space separated coodinates', () => {
+      expect(validateSpherical('1.1 2.1 3.1')).toBe(true);
+    });
+    test('should return true for space separated coodinates with leading/trailing spaces', () => {
+      expect(validateSpherical('  1.1  2.1 3.1 ')).toBe(true);
+    });
+    test('should return true for an array of parsable strings', () => {
+      expect(validateSpherical(['1.1', '2.1', '3.1'])).toBe(true);
+    });
+    test('should return true for an array of numbers', () => {
+      expect(validateSpherical([1.1, 2.1, 3.1])).toBe(true);
+    });
+    test('should return true for a Spherical instance', () => {
+      expect(validateSpherical(new Spherical(1.1, 2.1, 3.1))).toBe(true);
+    });
+    test('should return false for a string contains too many coodinates', () => {
+      expect(validateSpherical('1.1 2.1 3.1 4.1')).toBe(false);
+    });
+    test('should return false for a string contains too less coodinates', () => {
+      expect(validateSpherical('1.1 2.1')).toBe(false);
+    });
+    test('should return false for an array contains too many coodinate string', () => {
+      expect(validateSpherical(['1.1', '2.1', '3.1', '4.1'])).toBe(false);
+    });
+    test('should return false for an array contains too many coodinate number', () => {
+      expect(validateSpherical([1.1, 2.1, 3.1, 4.1])).toBe(false);
+    });
+    test('should return false for an array contains too less coodinate string', () => {
+      expect(validateSpherical(['1.1', '2.1'])).toBe(false);
+    });
+    test('should return false for an array contains too less coodinate number', () => {
+      expect(validateSpherical([1.1, 2.1])).toBe(false);
+    });
+    test('should return false for a string contains non-parsable coodinates', () => {
+      expect(validateSpherical('1.1 abc 4.1')).toBe(false);
+    });
+    test('should return false for an array contains non-parsable coodinate string', () => {
+      expect(validateSpherical(['1.1', 'abc', '4.1'])).toBe(false);
+    });
+  });
+  describe('validateFloatArray()', () => {
+    test('should return true for comma separated numbers string', () => {
+      expect(validateFloatArray('1.1, 2.1, 3.1, 4.1')).toBe(true);
+    });
+    test('should return true for an array of parsable strings', () => {
+      expect(validateFloatArray(['1.1', '2.2', '3.3', '4.4'])).toBe(true);
+    });
+    test('should return true for an array of numbers', () => {
+      expect(validateFloatArray([1.1, 2.2, 3.3, 4.4])).toBe(true);
+    });
+    test('should return false for a string contains non-parsable coodinates', () => {
+      expect(validateFloatArray('1.1, abc, 3.1, 4.1')).toBe(false);
+    });
+    test('should return false for an array contains non-parsable coodinate string', () => {
+      expect(validateFloatArray(['1.1', 'abc', '3.1', '4.1'])).toBe(false);
+    });
+  });
+  describe('validateVector2Array()', () => {
+    test('should return true for comma and space separated numbers string', () => {
+      expect(validateVector2Array('1.1 2.1, 3.1 4.1')).toBe(true);
+    });
+    test('should return true for an array of parsable strings', () => {
+      expect(validateVector2Array(['1.1 2.2', '3.3 4.4'])).toBe(true);
+    });
+    test('should return true for an array of arrays of strings', () => {
+      expect(validateVector2Array([['1.1', '2.2'], ['3.3', '4.4']])).toBe(true);
+    });
+    test('should return true for an array of arrays of numbers', () => {
+      expect(validateVector2Array([[1.1, 2.2], [3.3, 4.4]])).toBe(true);
+    });
+    test('should return true for an array of Vector2s', () => {
+      expect(validateVector2Array([new Vector2(1.1, 2.2), new Vector2(3.3, 4.4)])).toBe(true);
+    });
+    test('should return false for a string contains non-parsable coodinates', () => {
+      expect(validateVector2Array('1.1 abc, 3.1 4.1')).toBe(false);
+    });
+    test('should return false for an array contains non-parsable coodinate string', () => {
+      expect(validateVector2Array(['1.1 abc', '3.1 4.1'])).toBe(false);
+    });
+  });
+});