Skip to content

Instantly share code, notes, and snippets.

@maksbotan
Created February 6, 2020 05:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maksbotan/14b4bebda2acab98cdd158f85a970855 to your computer and use it in GitHub Desktop.
Save maksbotan/14b4bebda2acab98cdd158f85a970855 to your computer and use it in GitHub Desktop.
Example of type-level validation in python
from dataclasses import dataclass
from typing import Generic, Optional, TypeVar
class Raw:
pass
class Valid:
pass
V = TypeVar("V", Raw, Valid)
T = TypeVar("T")
class Validable(Generic[V, T]):
def __init__(self, a: T):
self.a = a
def validateAge(x: Validable[Raw, int]) -> Optional[Validable[Valid, int]]:
if x.a > 0:
return Validable(x.a)
else:
return None
@dataclass
class Input(Generic[V]):
name: str
age: Validable[V, int]
@staticmethod
def from_json(json: dict) -> "Input[Raw]":
pass
def validateInput(x: Input[Raw]) -> Optional[Input[Valid]]:
vAge = validateAge(x.age)
if vAge is None:
return None
else:
return Input(x.name, vAge)
def business(x: Input[Valid]) -> None:
pass
data = {"name": "foo", "age": -5}
inp = Input.from_json(data)
# reveal_type(inp)
# note: Revealed type is 'val.Input[val.Raw]'
# business(inp)
# error: Argument 1 to "business" has incompatible type "Input[Raw]"; expected "Input[Valid]"
vInp = validateInput(inp)
if vInp is not None:
business(vInp)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment