Repository: pydantic/pydantic

Issue:
How to provide default value to StrictBool?
How can we provide a default value to a variable with type `StrictBool` in a way that is accepted by MyPy?

```py
from pydantic import BaseModel

class Flags(BaseModel):
    pretend: StrictBool = False  # MyPy does not like this
```



Discussion:
Booleans are hard to deal with in a type-hinting context because python explicitly disallows subclassing `bool`. I might be missing something, but I suspect there isn't a way that you can assign a default value without having to fight mypy at least a little.

The obvious choice would be to just use
```python
class Flags(BaseModel):
    pretend: StrictBool = False  # type: ignore
```
but that may cause type checking issues since `StrictBool` is (by necessity) a subclass of int, rather than bool. While this involves "turning off" mypy (which I would agree should generally be avoided), I think this use is small in enough in scope to merit the convenience.

Another option is to put the `StrictBool` import in an `if TYPE_CHECKING:` block, having it serve as an alias for `bool` when type checking:
```python
from typing import TYPE_CHECKING

from pydantic import BaseModel

if TYPE_CHECKING:
    StrictBool = bool
else:
    from pydantic import StrictBool

class Flags(BaseModel):
    pretend: StrictBool = False
```

This should behave properly with type checking, but is a little uglier everywhere you import it.

@samuelcolvin Do you think it could make sense to just put the above alias for `StrictBool` (and `RelaxedBool` if/when merged) directly into pydantic? Or perhaps into a `types.pyi` or similar? Any obvious downsides to that?
> @samuelcolvin Do you think it could make sense to just put the above alias for StrictBool (and RelaxedBool if/when merged) directly into pydantic? Or perhaps into a types.pyi or similar? Any obvious downsides to that?

Makes sense. 

Although my instinct is that the need for `StrictBool` will reduce a lot when #617 gets deployed.
Thanks for your responses! IMHO a stricter `bool` validation as implemented in #617 would be the cleanest solution. Until it is merged and released I can fall back on suppressing `MyPy` warnings of `bool` and `Strictbool` type mismatch.

Resolving patch:
diff --git a/pydantic/types.py b/pydantic/types.py
--- a/pydantic/types.py
+++ b/pydantic/types.py
@@ -188,24 +188,28 @@ class StrictStr(ConstrainedStr):
     strict = True
 
 
-class StrictBool(int):
-    """
-    StrictBool to allow for bools which are not type-coerced.
-    """
-
-    @classmethod
-    def __get_validators__(cls) -> 'CallableGenerator':
-        yield cls.validate
+if TYPE_CHECKING:
+    StrictBool = bool
+else:
 
-    @classmethod
-    def validate(cls, value: Any) -> bool:
+    class StrictBool(int):
         """
-        Ensure that we only allow bools.
+        StrictBool to allow for bools which are not type-coerced.
         """
-        if isinstance(value, bool):
-            return value
 
-        raise errors.StrictBoolError()
+        @classmethod
+        def __get_validators__(cls) -> 'CallableGenerator':
+            yield cls.validate
+
+        @classmethod
+        def validate(cls, value: Any) -> bool:
+            """
+            Ensure that we only allow bools.
+            """
+            if isinstance(value, bool):
+                return value
+
+            raise errors.StrictBoolError()
 
 
 class PyObject:


Test patch:
diff --git a/tests/mypy/success.py b/tests/mypy/success.py
--- a/tests/mypy/success.py
+++ b/tests/mypy/success.py
@@ -8,12 +8,16 @@
 from datetime import datetime
 from typing import Generic, List, Optional, TypeVar
 
-from pydantic import BaseModel, NoneStr
+from pydantic import BaseModel, NoneStr, StrictBool
 from pydantic.dataclasses import dataclass
 from pydantic.fields import Field
 from pydantic.generics import GenericModel
 
 
+class Flags(BaseModel):
+    strict_bool: StrictBool = False
+
+
 class Model(BaseModel):
     age: int
     first_name = 'John'