Repository: ramonhagenaars/nptyping

Issue:
Some issues on boolean type.
Thank you for your work on type hinting of numpy and I benefitted a lot.

In the previous version, which `Array` was still not removed, everything worked fine. But when I updated and found I couldn't deal with boolean type with it. Here is the MWE. I wonder if it is possible the maintainer could give some help ...

MWE:

```
Python 3.7.5 (default, Nov  1 2019, 02:16:23)
[Clang 11.0.0 (clang-1100.0.33.8)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> from nptyping import *
>>> NDArray[np.bool]
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/typish/classes/_cls_function.py", line 68, in __call__
    return callable_(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 65, in _get_type_type
    return delegate(type_)
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 131, in get_type_int
    int: DEFAULT_INT_BITS,
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 98, in _get_type_of_number
    .format(type(obj).__name__, cls))
TypeError: Unsupported type type for Int
......
SOME ERROR INFO HERE
......
>>> NDArray[bool]
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/typish/classes/_cls_function.py", line 68, in __call__
    return callable_(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 65, in _get_type_type
    return delegate(type_)
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 131, in get_type_int
    int: DEFAULT_INT_BITS,
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 98, in _get_type_of_number
    .format(type(obj).__name__, cls))
TypeError: Unsupported type type for Int
......
SOME ERROR INFO EHRE
```

My environment:
- macOS 10.15.1
- Python 3.7.5
- nptyping 1.1.0
- numpy 1.18.5

<details><summary>FULL ERROR LOG</summary>
<p>

```shell
Python 3.7.5 (default, Nov  1 2019, 02:16:23)
[Clang 11.0.0 (clang-1100.0.33.8)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> from nptyping import *
>>> NDArray[np.bool]
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/typish/classes/_cls_function.py", line 68, in __call__
    return callable_(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 65, in _get_type_type
    return delegate(type_)
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 131, in get_type_int
    int: DEFAULT_INT_BITS,
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 98, in _get_type_of_number
    .format(type(obj).__name__, cls))
TypeError: Unsupported type type for Int

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/typish/classes/_cls_function.py", line 68, in __call__
    return callable_(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/nptyping/types/_ndarray_meta.py", line 134, in _only_type
    cls._type = Any if item is Any else get_type(item)
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 45, in get_type
    return function(obj)
  File "/usr/local/lib/python3.7/site-packages/typish/classes/_cls_function.py", line 71, in __call__
    .format(args[0], err.args[0]))
TypeError: Unable to call function for '<class 'bool'>': Unsupported type type for Int

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/typish/classes/_subscriptable_type.py", line 37, in __getitem__
    result._after_subscription(item)
  File "/usr/local/lib/python3.7/site-packages/nptyping/types/_ndarray_meta.py", line 121, in _after_subscription
    method(item)
  File "/usr/local/lib/python3.7/site-packages/typish/classes/_cls_function.py", line 71, in __call__
    .format(args[0], err.args[0]))
TypeError: Unable to call function for '<class 'bool'>': Unable to call function for '<class 'bool'>': Unsupported type type for Int
>>> NDArray[bool]
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/typish/classes/_cls_function.py", line 68, in __call__
    return callable_(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 65, in _get_type_type
    return delegate(type_)
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 131, in get_type_int
    int: DEFAULT_INT_BITS,
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 98, in _get_type_of_number
    .format(type(obj).__name__, cls))
TypeError: Unsupported type type for Int

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/typish/classes/_cls_function.py", line 68, in __call__
    return callable_(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/nptyping/types/_ndarray_meta.py", line 134, in _only_type
    cls._type = Any if item is Any else get_type(item)
  File "/usr/local/lib/python3.7/site-packages/nptyping/functions/_get_type.py", line 45, in get_type
    return function(obj)
  File "/usr/local/lib/python3.7/site-packages/typish/classes/_cls_function.py", line 71, in __call__
    .format(args[0], err.args[0]))
TypeError: Unable to call function for '<class 'bool'>': Unsupported type type for Int

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/typish/classes/_subscriptable_type.py", line 37, in __getitem__
    result._after_subscription(item)
  File "/usr/local/lib/python3.7/site-packages/nptyping/types/_ndarray_meta.py", line 121, in _after_subscription
    method(item)
  File "/usr/local/lib/python3.7/site-packages/typish/classes/_cls_function.py", line 71, in __call__
    .format(args[0], err.args[0]))
TypeError: Unable to call function for '<class 'bool'>': Unable to call function for '<class 'bool'>': Unsupported type type for Int
```

</p>
</details>

Discussion:

Patch:
diff --git a/HISTORY.rst b/HISTORY.rst
index 0b9a7ac..e590ee1 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -3,7 +3,14 @@
 History
 -------
 
-1.1.0 (2020-30-05)
+1.2.0 (2020-06-20)
+++++++++++++++++++
+
+- Added ``Bool``
+- Added ``Datetime64``
+- Added ``Timedelta64``
+
+1.1.0 (2020-05-30)
 ++++++++++++++++++
 
 - Removed ``Array``
diff --git a/README.md b/README.md
index fb5a757..d018f67 100644
--- a/README.md
+++ b/README.md
@@ -220,6 +220,39 @@ Unicode[100]
 
 ```
 
+### (❒) Bool
+An nptyping equivalent of numpy bool.
+
+```python
+>>> from nptyping import Bool
+
+>>> Bool
+Bool
+
+```
+
+### (❒) Datetime64
+An nptyping equivalent of numpy datetime64.
+
+```python
+>>> from nptyping import Datetime64
+
+>>> Datetime64
+Datetime64
+
+```
+
+### (❒) Timedelta64
+An nptyping equivalent of numpy timedelta64.
+
+```python
+>>> from nptyping import Timedelta64
+
+>>> Timedelta64
+Timedelta64
+
+```
+
 ### (❒) Object
 An nptyping equivalent of numpy objects.
 
diff --git a/nptyping/__init__.py b/nptyping/__init__.py
index 1ec1508..9dc9c20 100644
--- a/nptyping/__init__.py
+++ b/nptyping/__init__.py
@@ -1,6 +1,9 @@
 from nptyping._meta import __version__
 from nptyping.functions._get_type import get_type
 from nptyping.functions._py_type import py_type
+from nptyping.types._bool import Bool
+from nptyping.types._datetime64 import Datetime64
+from nptyping.types._timedelta64 import Timedelta64
 from nptyping.types._ndarray import NDArray
 from nptyping.types._nptype import NPType
 from nptyping.types._number import (
diff --git a/nptyping/_meta.py b/nptyping/_meta.py
index 1d0af1f..4884844 100644
--- a/nptyping/_meta.py
+++ b/nptyping/_meta.py
@@ -1,5 +1,5 @@
 __title__ = 'nptyping'
-__version__ = '1.1.0'
+__version__ = '1.2.0'
 __author__ = 'Ramon Hagenaars'
 __author_email__ = 'ramon.hagenaars@gmail.com'
 __description__ = 'Type hints for Numpy.'
diff --git a/nptyping/functions/_get_type.py b/nptyping/functions/_get_type.py
index 25a75d3..13ed1b3 100644
--- a/nptyping/functions/_get_type.py
+++ b/nptyping/functions/_get_type.py
@@ -1,9 +1,12 @@
+from datetime import datetime, timedelta
 from typing import Any, Type, Dict
 
 import numpy
 from typish import ClsFunction
 
 from nptyping.functions._py_type import py_type
+from nptyping.types._bool import Bool
+from nptyping.types._datetime64 import Datetime64
 from nptyping.types._ndarray import NDArray
 from nptyping.types._nptype import NPType
 from nptyping.types._number import (
@@ -15,6 +18,7 @@ from nptyping.types._number import (
     DEFAULT_FLOAT_BITS
 )
 from nptyping.types._object import Object
+from nptyping.types._timedelta64 import Timedelta64
 from nptyping.types._unicode import Unicode
 
 
@@ -26,40 +30,12 @@ def get_type(obj: Any) -> Type['NPType']:
     :param obj: the object for which an nptyping type is to be returned.
     :return: a subclass of NPType.
     """
-    function = ClsFunction([
-        (NPType, lambda x: x),
-        (type, _get_type_type),
-        (int, get_type_int),
-        (float, get_type_float),
-        (str, get_type_str),
-        (numpy.dtype, _get_type_dtype),
-        (numpy.ndarray, _get_type_arrary),
-        (numpy.signedinteger, get_type_int),
-        (numpy.unsignedinteger, get_type_uint),
-        (numpy.floating, get_type_float),
-    ])
-
-    if not function.understands(obj):
-        raise TypeError('Type "{}" not understood.'.format(type(obj).__name__))
-
-    return function(obj)
+    return ClsFunction(_delegates)(obj)
 
 
 def _get_type_type(type_: type) -> Type['NPType']:
     # Return the nptyping type of a type.
-
-    delegates = [
-        (NPType, lambda x: x),
-        (str, get_type_str),
-        (int, get_type_int),
-        (float, get_type_float),
-        (numpy.signedinteger, get_type_int),
-        (numpy.unsignedinteger, get_type_uint),
-        (numpy.floating, get_type_float),
-        (object, lambda _: Object),
-    ]
-
-    for super_type, delegate in delegates:
+    for super_type, delegate in _delegates:
         if issubclass(type_, super_type):
             break
     return delegate(type_)
@@ -69,9 +45,12 @@ def _get_type_dtype(dtype: numpy.dtype) -> Type['NPType']:
     # Return the nptyping type of a numpy dtype.
     np_type_per_py_type = {
         type: _get_type_type,
+        bool: get_type_bool,
         int: get_type_int,
         float: get_type_float,
         str: get_type_str,
+        datetime: get_type_datetime64,
+        timedelta: get_type_timedelta64,
         object: lambda _: Object,
     }
     return np_type_per_py_type[(py_type(dtype))](dtype)
@@ -100,6 +79,16 @@ def _get_type_of_number(
     return cls[bits]
 
 
+# Library private.
+def get_type_bool(_: Any) -> Type[Bool]:
+    """
+    Return the NPType that corresponds to obj.
+    :param _: a bool compatible object.
+    :return: a Bool type.
+    """
+    return Bool
+
+
 # Library private.
 def get_type_str(obj: Any) -> Type[Unicode]:
     """
@@ -161,3 +150,44 @@ def get_type_float(obj: Any) -> Type[Float]:
         numpy.float64: 64,
         float: DEFAULT_FLOAT_BITS,
     })
+
+
+# Library private.
+def get_type_datetime64(_: Any) -> Type[Datetime64]:
+    """
+    Return the NPType that corresponds to obj.
+    :param _: a datetime compatible object.
+    :return: a Datetime64 type.
+    """
+    return Datetime64
+
+
+# Library private.
+def get_type_timedelta64(_: Any) -> Type[Timedelta64]:
+    """
+    Return the NPType that corresponds to obj.
+    :param _: a timedelta compatible object.
+    :return: a Timedelta64 type.
+    """
+    return Timedelta64
+
+
+_delegates = [
+    (NPType, lambda x: x),
+    (type, _get_type_type),
+    (bool, get_type_bool),
+    (int, get_type_int),
+    (float, get_type_float),
+    (str, get_type_str),
+    (datetime, get_type_datetime64),
+    (timedelta, get_type_timedelta64),
+    (numpy.datetime64, get_type_datetime64),
+    (numpy.timedelta64, get_type_timedelta64),
+    (numpy.signedinteger, get_type_int),
+    (numpy.unsignedinteger, get_type_uint),
+    (numpy.floating, get_type_float),
+    (numpy.bool_, get_type_bool),
+    (numpy.dtype, _get_type_dtype),
+    (numpy.ndarray, _get_type_arrary),
+    (object, lambda _: Object),
+]
diff --git a/nptyping/functions/_py_type.py b/nptyping/functions/_py_type.py
index 3ce1978..5dd2109 100644
--- a/nptyping/functions/_py_type.py
+++ b/nptyping/functions/_py_type.py
@@ -1,3 +1,4 @@
+from datetime import datetime, timedelta
 from typing import Union, Any
 
 import numpy as np
@@ -33,4 +34,7 @@ _TYPE_PER_KIND = {
     'f': float,
     'U': str,
     'O': object,
+    'b': bool,
+    'M': datetime,
+    'm': timedelta,
 }
diff --git a/nptyping/types/_bool.py b/nptyping/types/_bool.py
new file mode 100644
index 0000000..c81cb49
--- /dev/null
+++ b/nptyping/types/_bool.py
@@ -0,0 +1,37 @@
+from typing import Type, Any
+
+import numpy
+from typish import get_mro
+
+from nptyping.types._nptype import NPType
+
+
+class _BoolMeta(type):
+    def __repr__(cls):
+        return 'Bool'
+
+    __str__ = __repr__
+
+    def __instancecheck__(cls, instance: Any) -> bool:
+        from nptyping.functions._get_type import get_type_bool
+        bool_ = get_type_bool(instance)
+        return issubclass(bool_, cls)
+
+    def __subclasscheck__(cls, subclass: type) -> bool:
+        return Bool in get_mro(subclass)
+
+
+class Bool(NPType, numpy.bool_, metaclass=_BoolMeta):
+    """
+    Corresponds to numpy.bool_.
+    """
+
+    @classmethod
+    def type_of(cls, obj: Any) -> Type['Bool']:
+        """
+        Return the NPType that corresponds to obj.
+        :param obj: a string compatible object.
+        :return: a Unicode type.
+        """
+        from nptyping.functions._get_type import get_type_bool
+        return get_type_bool(obj)
diff --git a/nptyping/types/_datetime64.py b/nptyping/types/_datetime64.py
new file mode 100644
index 0000000..f2d3ff8
--- /dev/null
+++ b/nptyping/types/_datetime64.py
@@ -0,0 +1,37 @@
+from typing import Type, Any
+
+import numpy
+from typish import get_mro
+
+from nptyping.types._nptype import NPType
+
+
+class _Datetime64Meta(type):
+    def __repr__(cls):
+        return 'Datetime64'
+
+    __str__ = __repr__
+
+    def __instancecheck__(cls, instance: Any) -> bool:
+        from nptyping.functions._get_type import get_type_datetime64
+        datetime_ = get_type_datetime64(instance)
+        return issubclass(datetime_, cls)
+
+    def __subclasscheck__(cls, subclass: type) -> bool:
+        return Datetime64 in get_mro(subclass)
+
+
+class Datetime64(NPType, numpy.datetime64, metaclass=_Datetime64Meta):
+    """
+    Corresponds to numpy.datetime64.
+    """
+
+    @classmethod
+    def type_of(cls, obj: Any) -> Type['Bool']:
+        """
+        Return the NPType that corresponds to obj.
+        :param obj: a string compatible object.
+        :return: a Datetime64 type.
+        """
+        from nptyping.functions._get_type import get_type_datetime64
+        return get_type_datetime64(obj)
diff --git a/nptyping/types/_ndarray.py b/nptyping/types/_ndarray.py
index c50c333..8345277 100644
--- a/nptyping/types/_ndarray.py
+++ b/nptyping/types/_ndarray.py
@@ -5,7 +5,7 @@ import numpy as np
 from nptyping.types._ndarray_meta import _NDArray
 
 
-class NDArray(np.ndarray, _NDArray):
+class NDArray(_NDArray, np.ndarray):
     """
     NDArray is a representation of numpy.ndarray.
 
diff --git a/nptyping/types/_nptype.py b/nptyping/types/_nptype.py
index d47979e..5b68ae7 100644
--- a/nptyping/types/_nptype.py
+++ b/nptyping/types/_nptype.py
@@ -5,6 +5,8 @@ class NPType:
     """
     The baseclass of all nptyping types.
     """
+    def __new__(cls, *args, **kwargs) -> None:
+        raise TypeError('Type {} cannot be instantiated'.format(cls.__name__))
 
 
 class SimpleNPTypeMeta(SubscriptableType):
diff --git a/nptyping/types/_number.py b/nptyping/types/_number.py
index ba8bf61..53f14ae 100644
--- a/nptyping/types/_number.py
+++ b/nptyping/types/_number.py
@@ -44,9 +44,7 @@ class _NumberMeta(SimpleNPTypeMeta):
         elif _is_a(subclass, Number):
             # Cover nptyping number types.
             result = _is_number_subclass_of(subclass, cls)
-        elif (issubclass(subclass, numpy.number)
-              or issubclass(subclass, int)
-              or issubclass(subclass, float)):
+        elif _is_number_type(subclass):
             result = _is_numpy_or_python_type_subclass_of(subclass, cls)
         return result
 
@@ -204,6 +202,13 @@ def _is_numpy_or_python_type_subclass_of(
     return result
 
 
+def _is_number_type(type_: type) -> bool:
+    # Return whether type_ is a numpy/Python number type.
+    return (issubclass(type_, numpy.number)
+            or issubclass(type_, int)
+            or issubclass(type_, float))
+
+
 Int8 = Int[8]
 Int16 = Int[16]
 Int32 = Int[32]
diff --git a/nptyping/types/_object.py b/nptyping/types/_object.py
index a0f795a..ad5bf17 100644
--- a/nptyping/types/_object.py
+++ b/nptyping/types/_object.py
@@ -1,3 +1,5 @@
+import numpy
+
 from nptyping.types._nptype import NPType
 
 
@@ -8,7 +10,7 @@ class _ObjectMeta(type):
     __str__ = __repr__
 
 
-class Object(NPType, metaclass=_ObjectMeta):
+class Object(NPType, numpy.generic, metaclass=_ObjectMeta):
     """
     Corresponds to numpy.object.
     """
diff --git a/nptyping/types/_timedelta64.py b/nptyping/types/_timedelta64.py
new file mode 100644
index 0000000..99cb775
--- /dev/null
+++ b/nptyping/types/_timedelta64.py
@@ -0,0 +1,37 @@
+from typing import Type, Any
+
+import numpy
+from typish import get_mro
+
+from nptyping.types._nptype import NPType
+
+
+class _Timedelta64Meta(type):
+    def __repr__(cls):
+        return 'Timedelta64'
+
+    __str__ = __repr__
+
+    def __instancecheck__(cls, instance: Any) -> bool:
+        from nptyping.functions._get_type import get_type_timedelta64
+        timedelta_ = get_type_timedelta64(instance)
+        return issubclass(timedelta_, cls)
+
+    def __subclasscheck__(cls, subclass: type) -> bool:
+        return Timedelta64 in get_mro(subclass)
+
+
+class Timedelta64(NPType, numpy.timedelta64, metaclass=_Timedelta64Meta):
+    """
+    Corresponds to numpy.timedelta64.
+    """
+
+    @classmethod
+    def type_of(cls, obj: Any) -> Type['Bool']:
+        """
+        Return the NPType that corresponds to obj.
+        :param obj: a string compatible object.
+        :return: a Timedelta64 type.
+        """
+        from nptyping.functions._get_type import get_type_timedelta64
+        return get_type_timedelta64(obj)
diff --git a/nptyping/types/_unicode.py b/nptyping/types/_unicode.py
index a490d57..017d1a2 100644
--- a/nptyping/types/_unicode.py
+++ b/nptyping/types/_unicode.py
@@ -1,5 +1,6 @@
 from typing import Any, Type
 
+import numpy
 from typish import get_mro
 
 from nptyping.types._nptype import NPType, SimpleNPTypeMeta
@@ -26,7 +27,7 @@ class _UnicodeMeta(SimpleNPTypeMeta):
         return False
 
 
-class Unicode(NPType, metaclass=_UnicodeMeta):
+class Unicode(NPType, numpy.unicode, metaclass=_UnicodeMeta):
     """
     A numpy unicode. Can be given the number of characters optionally.
 


Test patch:
diff --git a/tests/test_functions/test_get_type.py b/tests/test_functions/test_get_type.py
index 6a96a6b..3f7e4ca 100644
--- a/tests/test_functions/test_get_type.py
+++ b/tests/test_functions/test_get_type.py
@@ -1,3 +1,4 @@
+from datetime import datetime, timedelta
 from unittest import TestCase
 
 import numpy as np
@@ -20,8 +21,10 @@ from nptyping import (
     DEFAULT_INT_BITS,
     DEFAULT_FLOAT_BITS,
     Float,
-)
+    Bool,
+    Datetime64)
 from nptyping.types._object import Object
+from nptyping.types._timedelta64 import Timedelta64
 from nptyping.types._unicode import Unicode
 
 
@@ -36,10 +39,14 @@ class TestGetType(TestCase):
     def test_get_type_str(self):
         self.assertEqual(Unicode[4], get_type('Test'))
 
+    def test_get_type_bool(self):
+        self.assertEqual(Bool, get_type(True))
+
     def test_get_type_nptype(self):
         self.assertEqual(Int32, get_type(Int32))
         self.assertEqual(Float64, get_type(Float64))
         self.assertEqual(Unicode[100], get_type(Unicode[100]))
+        self.assertEqual(Bool, get_type(Bool))
 
     def test_get_type_numpy_dtype(self):
         self.assertEqual(Int8, get_type(np.int8(42)))
@@ -59,6 +66,21 @@ class TestGetType(TestCase):
         self.assertEqual(Unicode, get_type(np.unicode))
         self.assertEqual(Unicode[40], get_type(np.dtype(('U', 40))))
 
+        self.assertEqual(Bool, get_type(np.bool_(True)))
+        self.assertEqual(Bool, get_type(np.bool_(False)))
+
+    def test_get_type_datatime(self):
+        self.assertEqual(Datetime64, get_type(datetime.now()))
+        self.assertEqual(Datetime64, get_type(datetime))
+        self.assertEqual(Datetime64, get_type(np.datetime64))
+        self.assertEqual(Datetime64, get_type(np.datetime64()))
+
+    def test_get_type_timedelta(self):
+        self.assertEqual(Timedelta64, get_type(timedelta(days=42)))
+        self.assertEqual(Timedelta64, get_type(timedelta))
+        self.assertEqual(Timedelta64, get_type(np.timedelta64))
+        self.assertEqual(Timedelta64, get_type(np.timedelta64()))
+
     def test_get_type_numpy_type(self):
         self.assertEqual(Int8, get_type(np.int8))
         self.assertEqual(Int16, get_type(np.int16))
@@ -74,17 +96,16 @@ class TestGetType(TestCase):
         self.assertEqual(Float32, get_type(np.float32))
         self.assertEqual(Float64, get_type(np.float64))
 
+        self.assertEqual(Bool, get_type(np.bool_))
+
     def test_get_type_object(self):
         self.assertEqual(Object, get_type(np.object))
 
     def test_get_type_array(self):
         self.assertEqual(NDArray[3, Int[DEFAULT_INT_BITS]], get_type(np.array([1, 2, 3])))
 
-    def test_get_type_not_understood(self):
+    def test_get_type_some_random_class(self):
         class SomeRandomClass:
             ...
 
-        # Test invalid instances.
-        with self.assertRaises(TypeError) as err:
-            get_type(SomeRandomClass())
-        self.assertIn(SomeRandomClass.__name__, str(err.exception))
+        self.assertEqual(Object, get_type(SomeRandomClass()))
diff --git a/tests/test_functions/test_py_type.py b/tests/test_functions/test_py_type.py
index ba72ab2..f23ae2a 100644
--- a/tests/test_functions/test_py_type.py
+++ b/tests/test_functions/test_py_type.py
@@ -1,3 +1,4 @@
+from datetime import datetime, timedelta
 from unittest import TestCase
 
 import numpy as np
@@ -22,3 +23,6 @@ class TestPyType(TestCase):
         self.assertIs(float, py_type(np.float16))
         self.assertIs(float, py_type(np.float32))
         self.assertIs(float, py_type(np.float64))
+
+        self.assertIs(datetime, py_type(np.datetime64))
+        self.assertIs(timedelta, py_type(np.timedelta64))
diff --git a/tests/test_types/test_bool.py b/tests/test_types/test_bool.py
new file mode 100644
index 0000000..7ff6212
--- /dev/null
+++ b/tests/test_types/test_bool.py
@@ -0,0 +1,26 @@
+from unittest import TestCase
+
+import numpy
+
+from nptyping import Bool
+
+
+class TestBool(TestCase):
+
+    def test_isinstance(self):
+        self.assertIsInstance(True, Bool)
+        self.assertIsInstance(False, Bool)
+
+        self.assertIsInstance(numpy.bool_(True), Bool)
+        self.assertIsInstance(numpy.bool_(False), Bool)
+
+    def test_repr(self):
+        self.assertEqual('Bool', repr(Bool))
+
+    def test_bool_of(self):
+        self.assertEqual(Bool, Bool.type_of(True))
+        self.assertEqual(Bool, Bool.type_of(False))
+        self.assertEqual(Bool, Bool.type_of(numpy.bool_))
+        self.assertEqual(Bool, Bool.type_of(numpy.bool_(True)))
+        self.assertEqual(Bool, Bool.type_of(numpy.bool_(False)))
+        self.assertEqual(Bool, Bool.type_of(1))
diff --git a/tests/test_types/test_datetime64.py b/tests/test_types/test_datetime64.py
new file mode 100644
index 0000000..434848f
--- /dev/null
+++ b/tests/test_types/test_datetime64.py
@@ -0,0 +1,19 @@
+from datetime import datetime
+from unittest import TestCase
+
+import numpy
+
+from nptyping import Datetime64
+
+
+class TestDatetime64(TestCase):
+
+    def test_isinstance(self):
+        self.assertIsInstance(datetime.now(), Datetime64)
+        self.assertIsInstance(numpy.datetime64(datetime.now()), Datetime64)
+
+    def test_repr(self):
+        self.assertEqual('Datetime64', repr(Datetime64))
+
+    def test_type_of(self):
+        self.assertEqual(Datetime64, Datetime64.type_of(datetime.now()))
diff --git a/tests/test_types/test_ndarray.py b/tests/test_types/test_ndarray.py
index 16de20c..0f9a1da 100644
--- a/tests/test_types/test_ndarray.py
+++ b/tests/test_types/test_ndarray.py
@@ -3,7 +3,8 @@ from unittest import TestCase
 
 import numpy as np
 
-from nptyping import NDArray, DEFAULT_INT_BITS, Int
+from nptyping import NDArray, DEFAULT_INT_BITS, Int, Bool, Datetime64
+from nptyping.types._timedelta64 import Timedelta64
 
 
 class TestNDArray(TestCase):
@@ -31,6 +32,8 @@ class TestNDArray(TestCase):
     def test_initialize_with_type(self):
         self.assertEqual((Any, ...), NDArray[int].shape)
         self.assertEqual(Int[DEFAULT_INT_BITS], NDArray[int]._type)
+        self.assertEqual(Int, NDArray[Int]._type)
+        self.assertEqual(Bool, NDArray[Bool]._type)
 
     def test_initialize_with_size_and_type(self):
         self.assertEqual(1, len(NDArray[3, int].shape))
@@ -166,16 +169,19 @@ class TestNDArray(TestCase):
         arr2 = np.array([1, 2, '3'])
         arr3 = np.array([1, 2, 3.0])
         arr4 = np.array([1, 2, {}])
+        arr5 = np.array([True, True, True])
 
         t1 = NDArray.type_of(arr1)
         t2 = NDArray.type_of(arr2)
         t3 = NDArray.type_of(arr3)
         t4 = NDArray.type_of(arr4)
+        t5 = NDArray.type_of(arr5)
 
         self.assertIsInstance(arr1, t1)
         self.assertIsInstance(arr2, t2)
         self.assertIsInstance(arr3, t3)
         self.assertIsInstance(arr4, t4)
+        self.assertIsInstance(arr5, t5)
 
     def test_hash_ndarray(self):
         # Hashing should not raise.
@@ -184,3 +190,15 @@ class TestNDArray(TestCase):
         # You should now be able to wrap an NDArray in an optional.
         Optional[NDArray[(3,), int]]
         Optional[NDArray]
+
+    def test_instantiate(self):
+        with self.assertRaises(TypeError) as err:
+            NDArray([1, 2, 3])
+
+        self.assertIn('NDArray', str(err.exception))
+
+    def test_instance_check_with_np_types(self):
+        self.assertIsInstance(np.array([[True, False], [True, False]]), NDArray[(Any, ...), Bool])
+        self.assertNotIsInstance(np.array([[True, False], [True, 42]]), NDArray[(Any, ...), Bool])
+        self.assertIsInstance(np.array([np.datetime64()]), NDArray[(Any, ...), Datetime64])
+        self.assertIsInstance(np.array([np.timedelta64()]), NDArray[(Any, ...), Timedelta64])
diff --git a/tests/test_types/test_timedelta64.py b/tests/test_types/test_timedelta64.py
new file mode 100644
index 0000000..9f5cb2a
--- /dev/null
+++ b/tests/test_types/test_timedelta64.py
@@ -0,0 +1,19 @@
+from datetime import timedelta
+from unittest import TestCase
+
+import numpy
+
+from nptyping.types._timedelta64 import Timedelta64
+
+
+class TestTimedelta64(TestCase):
+
+    def test_isinstance(self):
+        self.assertIsInstance(timedelta(days=1), Timedelta64)
+        self.assertIsInstance(numpy.timedelta64(1), Timedelta64)
+
+    def test_repr(self):
+        self.assertEqual('Timedelta64', repr(Timedelta64))
+
+    def test_type_of(self):
+        self.assertEqual(Timedelta64, Timedelta64.type_of(timedelta(days=42)))