Fundamentals 7 min read

New Typing Features in Python 3.13: ReadOnly, @warnings.deprecated, TypeIs, is_protocol, get_protocol_members, Default TypeVars, NoDefault and Performance Improvements

Python 3.13 adds seven new typing enhancements—including ReadOnly TypedDict fields, a @warnings.deprecated decorator, TypeIs for type narrowing, is_protocol and get_protocol_members utilities, default TypeVar support, the NoDefault sentinel, and import‑time optimizations—each illustrated with code examples.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
New Typing Features in Python 3.13: ReadOnly, @warnings.deprecated, TypeIs, is_protocol, get_protocol_members, Default TypeVars, NoDefault and Performance Improvements

Python 3.13 introduces seven new typing features that enhance code reliability and developer productivity.

The ReadOnly type can be used inside TypedDict to mark specific fields as immutable, causing type‑checkers to flag assignments to those fields.

<code>from typing import TypedDict, ReadOnly

class Leader(TypedDict):
    name: ReadOnly[str]
    age: int

author: Leader = {'name': 'Yang Zhou', 'age': 30}
author['age'] = 31  # ok
author['name'] = 'Yang'  # Type check error
</code>

A simpler syntax also allows ReadOnly directly in the TypedDict definition.

<code>from typing import TypedDict, ReadOnly

Leader = TypedDict('Leader', {'name': ReadOnly[str], 'age': int})
author: Leader = {'name': 'Yang Zhou', 'age': 30}
author['age'] = 31
author['name'] = 'Tim'  # Type check error
</code>

The new @warnings.deprecated decorator marks functions or classes as deprecated; IDEs such as PyCharm will display a strikethrough warning.

Python 3.13 adds the TypeIs protocol for more precise type narrowing, allowing functions to return True when an argument conforms to a narrower type.

The is_protocol function quickly checks whether an object is a Protocol type.

<code>from typing import is_protocol, Protocol

class PersonProto(Protocol):
    name: str
    age: int

print(is_protocol(PersonProto))  # True
print(is_protocol(int))         # False
</code>

The get_protocol_members function returns a frozenset of member names defined in a protocol.

<code>from typing import Protocol, get_protocol_members

class PersonProto(Protocol):
    name: str
    age: int

print(get_protocol_members(PersonProto))  # frozenset({'age', 'name'})
</code>

Type variables ( TypeVar ), ParamSpec , and TypeVarTuple now support default types via the default= argument, and the has_default() method can query this.

<code>from typing import TypeVar
T = TypeVar('T', default=int)
print(T.has_default())  # True
S = TypeVar('S')
print(S.has_default())  # False
</code>

The new NoDefault sentinel indicates that a type variable has no default value.

<code>from typing import TypeVar, NoDefault
T = TypeVar('T')
print(T.__default__ is NoDefault)  # True
S = TypeVar('S', default=None)
print(S.__default__ is NoDefault)  # False
</code>

Performance improvements include removing the deprecated typing.io and typing.re namespaces and the keyword‑argument method for creating TypedDict , reducing import time of the typing module by about one‑third.

PythonReadOnlytype hintstypingPython 3.13TypeVar
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.