Skip to content

Add blog post on why type-coverage matters - #4518

Open
MarcoGorelli wants to merge 1 commit into
facebook:mainfrom
MarcoGorelli:why-coverage
Open

Add blog post on why type-coverage matters#4518
MarcoGorelli wants to merge 1 commit into
facebook:mainfrom
MarcoGorelli:why-coverage

Conversation

@MarcoGorelli

@MarcoGorelli MarcoGorelli commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

I've put together a little blog post to explain what type coverage is, and why people might want to make use of it

Fixes #XXXX

Test Plan

@meta-codesync

meta-codesync Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

This pull request has been imported. If you are a Meta employee, you can view this in D115732206. (Because this pull request was imported automatically, there will not be any future comments.)

@MarcoGorelli
MarcoGorelli marked this pull request as ready for review August 12, 2026 16:28
@github-actions
github-actions Bot requested a review from connernilsen August 13, 2026 09:31

@grievejia grievejia left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review automatically exported from Phabricator review in Meta.

@jorenham
jorenham self-requested a review August 14, 2026 15:17

@jorenham jorenham left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thanks. I left some suggestions; feel free to ignore any of them.


## What's type coverage?

Similarly to how test coverage measures how much of a library's source code is hit by its tests, type coverage measures what percentage of a library's symbols have type annotations. Examples of symbols which get counted include function arguments and return types, class variables, and constants. Local variables in function bodies are excluded, as users would never interact with them anyway.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been calling them "typables", because there are symbols for which it doens't make much sense to type them, and because return types aren't really symbols.

I guess you could describe it as "a typable is something that can meaningfully annotated". I use "meaningfully" because there are typables where annotating it wouldn't be meaningfull, such as the return type of __init__ because that's always None, so annotating it wouldn't help much.

So although quite a bit will have to be rewritten, it'd probably be clearer if this would talk about these "typables" instead of "symbols". It'll at least be more accurate that way. Another benefit of using "typables" and actually defining what it means, is that it'll show that we've carefully thought out these coverage metrics (unlike pyright's --verifytypes, for example).

But even so, I'm probably the only one that cares about this detail haha; I'm sure the casual reader wouldn't even think twice about what exactly "symbol" means here.

Comment on lines +41 to +44
Note how there are two issues with the stub file:

- The `c` parameter in `two` is misnamed (it should be `b`). It's also unannotated.
- The `three` function is missing entirely.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can imagine some users could be confused by this, because they might think that type-checkers fall back to the inline annotations if not present in the stub. So it might be worth explaining here that if a .pyi exists, type-checkers only look at that .pyi, completely ignoring the corresponding .py if it exists.


Pyrefly coverage is a new-ish feature, yet it's already being used by a few projects:

- [SciPy](https://github.com/scipy/scipy).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SciPy itself doesn't use pyrefly coverage (it just uses pyrefly check), so I think you mean scipy-stubs.

Suggested change
- [SciPy](https://github.com/scipy/scipy).
- [SciPy (stubs)](https://github.com/scipy/scipy-stubs).

or just

Suggested change
- [SciPy](https://github.com/scipy/scipy).
- [scipy-stubs](https://github.com/scipy/scipy-stubs).

Comment on lines +82 to +84
- [NumPy](https://github.com/numpy/numpy).
- [Narwhals](https://github.com/narwhals-dev/narwhals).
- [sh](https://github.com/amoffat/sh).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also include polars (pola-rs/polars#28795)?

Suggested change
- [NumPy](https://github.com/numpy/numpy).
- [Narwhals](https://github.com/narwhals-dev/narwhals).
- [sh](https://github.com/amoffat/sh).
- [NumPy](https://github.com/numpy/numpy).
- [Polars](https://github.com/pola-rs/polars).
- [Narwhals](https://github.com/narwhals-dev/narwhals).
- [sh](https://github.com/amoffat/sh).


## Who's using it?

Pyrefly coverage is a new-ish feature, yet it's already being used by a few projects:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Pyrefly coverage is a new-ish feature, yet it's already being used by a few projects:
Pyrefly coverage is a new-ish feature, yet it's already being used by a few major projects:

maybe?

Comment on lines +48 to +63
```console
WARN `foo.three` is untyped [coverage-missing]
--> src/foo/__init__.py:7:1
|
7 | / def three() -> None:
8 | | return None
| |_______________-
|
WARN `foo.two` is not fully typed [coverage-partial]
--> src/foo/__init__.pyi:2:1
|
2 | def two(c) -> None: ...
| -----------------------
|
ERROR type coverage 60.00% (3 of 5 typable) is below the 100.00% threshold
```

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe include the full pyrefly coverage check command in here?

Comment on lines +32 to +34
- `def one(a: int) -> int`
- `def two(b: int) -> None`
- `def three() -> None`

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inspired by https://youtu.be/u8ccGjar4Es 😛 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants