NewType in Python
Source: Dev.to
Overview
NewType allows you to create a distinct type that is treated as a separate type by static type checkers (e.g., mypy) while being a runtime alias for its base type. It has been available since Python 3.5.2.
Key Characteristics
- The new type is unique and different from its base type.
- It can be created only from a non‑union (i.e., non‑
typing.Union) type. - The resulting type behaves like a subtype‑like type of its base.
- It cannot be subclassed with a regular class.
Syntax
from typing import NewType, reveal_type
# name: required string, must match the variable name
# tp: required non‑union type
NT1 = NewType('NT1', int)
NT2 = NewType('NT2', list[int | float])
Important notes
- The first argument (
name) is a string that should be identical to the variable name. - The second argument (
tp) must be a concrete, non‑union type. - Using a union type (e.g.,
int | float) raises an error.
Basic Usage
from typing import NewType, reveal_type
NT1 = NewType('NT1', int)
NT2 = NewType('NT2', list[int | float])
reveal_type(NT1(100)) # -> int (type checker shows test.NT1)
reveal_type(NT2([0, 1, 2])) # -> list (type checker shows test.NT2)
# The following are errors (type checker / runtime):
# NT3 = NewType('NT3', int | float) # ❌ Union not allowed
# NT50 = NewType('NT100', int) # ❌ Name mismatch
Interaction Between NewTypes
from typing import NewType
NT1 = NewType('NT1', int)
NT2 = NewType('NT2', NT1)
# Assignments
a1: NT1 = 100 # ❌ Error
a2: NT1 = NT1(100) # ✅ No error
a3: NT1 = NT2(100) # ❌ Error
a4: NT1 = NT2(NT1(100)) # ✅ No error
a5: NT1 = NT1(NT2(100)) # ❌ Error
b1: NT2 = 100 # ❌ Error
b2: NT2 = NT1(100) # ❌ Error
b3: NT2 = NT2(100) # ❌ Error
b4: NT2 = NT2(NT1(100)) # ✅ No error
b5: NT2 = NT1(NT2(100)) # ❌ Error
c1: int = 100 # ✅ No error
c2: int = NT1(100) # ✅ No error
c3: int = NT2(100) # ❌ Error
c4: int = NT2(NT1(100)) # ✅ No error
c5: int = NT1(NT2(100)) # ❌ Error
print(a4 + b4 + c4) # ✅ No error
NewType with Type Aliases and Generics
from typing import NewType
type TA1 = int
type TA2[T] = T
NT1 = NewType('NT1', TA1) # ✅ No error
NT2 = NewType('NT2', TA2[int]) # ✅ No error
Invalid Generic Usage
from typing import NewType
NT = NewType('NT', list)
v: NT[int] # ❌ Error – NewType does not support generic parameters
Subclassing NewType
from typing import NewType
NT = NewType('NT', int)
class Cls(NT): # ❌ Error – NewType cannot be subclassed
pass
References
- Python documentation: typing.NewType
- Related memo: Memo for type‑hints‑related posts in Python
This article builds on earlier posts about type hints:
- Type hints in Python (part 1) (explains basic type hints)