Key Points
- TypeScript became the most-used language on GitHub in 2025 (about 2.64 million contributors monthly), overtaking Python and JavaScript. GitHub attributes much of this growth to AI-assisted coding, where type systems help catch machine-generated mistakes.
- The static-versus-dynamic binary is outdated. Gradual typing has become the current norm, with TypeScript and Python type hints allowing teams to add type safety incrementally.
- TypeScript 7.0 rewrote its compiler in Go, delivering roughly 10x faster builds than the previous JavaScript-based compiler.
When it comes to software development services, typing is one of the more consequential choices built into a programming language. It refers to how data and variables are categorized by their data types, such as integers, strings, or booleans. This categorization determines how a programming language handles and manipulates data.
For most of programming history, the conversation came down to two approaches: static typing and dynamic typing. Recently, a third approach has become quite common. It’s gradual typing, which blends the flexibility of dynamic languages with the safety of optional static checks.
What Is the Real Difference Between Static and Dynamic Typing?
Typing involves specifying the data type of a variable or allowing the programming language to deduce it automatically. It plays a role in ensuring the integrity of data and the reliability of code.
Static typing checks and binds a variable’s data type at compile time, so type mismatches are caught before the program runs. Dynamic typing defers type resolution to runtime, allowing a variable to hold different types during execution. Gradual typing combines both approaches by adding optional type annotations and external checkers to otherwise dynamic languages.

Static Typing
Static typing is a typing system where variables are bound to a data type during compilation. Once a variable is assigned a data type, it remains unchanged throughout the program’s execution. This binding promotes type safety and detects errors at an early stage.
The compiler validates every assignment and function call before producing an executable, so type mismatches surface during development.
Key Characteristics of Static Typing
One of the advantages of typing is ensuring type safety, which reduces the chances of runtime errors caused by mismatches in data types.
Another benefit is error detection. Since the compiler knows the data types during the development process, it can catch errors before runtime, resulting in reliable software.
Static typing also offers performance benefits. The compiler can optimize code effectively in languages with typing, potentially leading to faster execution.
Examples of Statically Typed Languages
Several programming languages adopt typing as their approach to handling data types. Here are a few notable examples.
- C++: A language commonly used for system programming and game development where data types must be explicitly defined.
- Java: A language that is known for its “Write Once Run Anywhere” capability which enforces strong typing through a reliable type system.
- Rust: An increasingly popular language that ensures memory safety and concurrency without sacrificing performance through static typing.
Dynamic Typing
In contrast, dynamic typing allows variables to be bound to data types at runtime instead of during compilation.
A variable can hold a string in one statement and a number in the next. Code tends to be more concise, and early prototyping moves faster, but type-related bugs can stay hidden until the affected code path actually runs.
Key Characteristics of Dynamic Typing
One of the advantages of typing is its flexibility. In dynamically typed languages, variables have the ability to change their data type during runtime. This allows for adaptability in situations.
Another benefit is the ease of use that dynamic typing provides. Unlike static typed languages developers in dynamic typed languages don’t need to explicitly specify data types when coding. This simplifies the coding process.
Runtime variable type re-checking is another feature offered by dynamic typing. During runtime the type of a variable is checked, which means any errors related to type mismatches might only be discovered at that point. While this can lead to issues it also offers flexibility in handling data types on the fly.
Examples of Dynamically Typed Languages
There are numerous programming languages that adopt dynamic typing due to its flexibility and simplicity.
- Python: A versatile language renowned for its readability and ease of use while relying on dynamic typing to provide concise code.
- JavaScript: A scripting language used for web development that uses dynamic typing to offer greater flexibility in handling data.
- Ruby: Known for its simplicity and elegant syntax. Ruby utilizes dynamic typing to make coding more intuitive and expressive..
Gradual Typing
Gradual typing sits between the two. The runtime stays dynamic, but you can annotate variables and function signatures so external tools can check them before execution. Most modern Python and JavaScript projects operate this way in practice.
Key Characteristics of Gradual Typing
One of the main advantages of gradual typing is incremental adoption. Teams can add type annotations to the parts of a codebase that need them most.
Another benefit is flexibility. Unannotated code continues to behave like any dynamic language, so types can be added as the project matures rather than all at once.
Gradual typing also provides early error detection where it counts. External checkers analyze annotated code before it runs, catching type mismatches with no runtime overhead from the annotations themselves.
Examples of Gradually Typed Languages
- TypeScript: A superset of JavaScript that adds optional static typing. TypeScript 7.0 rewrote its compiler in Go, delivering roughly 10x faster builds.
- Python with type hints: Python stays dynamically typed at runtime, but type hints paired with checkers like Pyright, mypy 2.x, Pyrefly, or ty provide static analysis without changing how the interpreter works.
- JavaScript with JSDoc types: Teams that prefer plain JavaScript can use JSDoc annotations to get type checking from the TypeScript language server without a compilation step.
Static, Dynamic, and Gradual Typing
| Aspect | Static Typing | Dynamic Typing | Gradual Typing |
| Determination Time | Determined at compile time | Determined at runtime | Determined at compile time where annotated, runtime elsewhere |
| Error Detection | Errors caught during compilation | Errors may appear during program execution | Errors caught before execution where annotated, runtime elsewhere |
| Performance | Typically faster due to compile-time optimizations | Possible overhead from runtime type-checks | Runtime performance of the dynamic language; static analysis adds no runtime cost |
| Coding Verbosity | Requires explicit type declarations | Concise; types are not specified explicitly | Annotations are optional; verbosity scales with how much you choose to annotate |
| Flexibility | Variables bound to one type | Variable types can change during execution | Dynamic by default; annotated variables are checked statically |
| Type Safety | High type safety through early error detection | Some type safety traded off for flexibility | Partial; as strong as the annotation coverage |
| Example Languages | C++, Java, Rust | Ruby, JavaScript | TypeScript, Python with type hints |
| Tooling | Native compilers | Linters | Pyright, mypy 2.x, Pyrefly, ty, TypeScript 7 Go compiler |
Strongly Typed Languages
Besides the distinction between static, dynamic, and gradual typing, there’s another dimension worth understanding: strong and weak typing.
Strongly typed languages enforce strict rules on type conversions, reducing the risk of unexpected behavior. Weakly typed languages are more permissive, silently converting between types in ways that can make code harder to debug.
Key Characteristics of Strongly Typed Languages
- Strongly typed languages are more rigid when it comes to type conversions, as they ensure that operations are performed only on compatible data types.
- By catching type-related errors early, strongly typed languages minimize runtime errors and make debugging easier.
- Strongly typed languages may require more explicit type annotations, which can make code slightly more verbose.
Examples of Strongly Typed Languages
Several programming languages combine strong typing with either static or dynamic typing. Some prominent examples include.
- C++: As mentioned earlier, C++ is both statically typed and strongly typed, providing a high degree of type safety.
- Java: Java’s type system enforces strong typing to avoid potential pitfalls related to type coercion.
- Python: Despite being dynamically typed, Python is also considered a strongly typed language as it ensures data integrity through strict type checking.
Which Type Checkers Should Python Teams Use in 2026?
Python remains dynamically typed at runtime, but the ecosystem now offers several mature static analysis tools. The main options in 2026 are:
- Pyright: Microsoft’s type checker, integrated into VS Code via Pylance. Fast, widely adopted, and developed alongside TypeScript tooling.
- mypy 2.x: The original Python type checker. Still widely used in CI pipelines and actively maintained.
- Pyrefly: Meta’s type checker, open-sourced in 2025, built for large-scale Python codebases with a focus on performance. A detailed comparison of Pyrefly and ty covers the trade-offs between the two newer tools.
- ty: Astral’s type checker, built in Rust, from the team behind Ruff. Optimized for speed in local development workflows.
Python 3.14 made two changes worth noting. Deferred annotation evaluation cuts the runtime cost of type hints, and free-threaded builds remove the GIL, giving CPython genuine parallelism for the first time. Full details are in the Python 3.14 release notes.
Adding type hints to a dynamic language is no longer a niche practice. It is how engineering teams who maintain large Python codebases in production keep refactors safe as headcount and AI-generated code grow. Pairing type hints with a checker such as Pyright or mypy catches mismatches before they reach runtime, making gradual typing the default approach instead of rewriting an application in a statically typed language.
Strongly Typed Languages Vs Static and Dynamic Typing
Now that we understand the concepts all types of typing, let’s compare them in greater detail.
Error detection
Strong typing and static typing both catch errors early, but through different mechanisms. Strong typing rejects invalid type operations outright, which prevents a whole category of bugs that weakly typed languages paper over with implicit conversions.
A weakly typed language, by contrast, will silently convert between types when it can, which makes code more permissive but harder to debug.
Performance
Performance tends to favor statically typed languages. Compilers use type information to optimize generated code, while dynamic languages do some of that work at runtime instead. That overhead is often small, but it adds up in tight loops or high-throughput systems.
Ease of Use
Dynamic typing is easier to write quickly, since there are no type declarations to maintain. That speed comes with a trade-off: type errors show up later, often only when a specific code path actually runs in production.
Type Safety
Gradual typing keeps the conciseness of dynamic code where you want it and adds safety where you need it. Most teams do not rewrite their Python or JavaScript codebase to get type safety. They annotate the critical paths and run a checker, which gives them the practical benefits of both without the cost of a full migration.
Why Did TypeScript Become the Most-Used Language on GitHub in 2025?
The numbers behind TypeScript’s growth show just how far gradual typing has come in practice.
TypeScript overtook Python and JavaScript in August 2025 to become the most-used language on GitHub. According to GitHub’s Octoverse 2025 report, GitHub described it as “the most significant language shift in more than a decade,” with TypeScript reaching approximately 2.64 million monthly contributors after gaining over one million in a single year.
Two things drove this. Nearly every major frontend framework now scaffolds with TypeScript by default, which has made it the path of least resistance for new JavaScript projects. Then, in July 2026, Microsoft released TypeScript 7.0 with the compiler rewritten in Go, delivering roughly 10x faster builds through native code speed and shared-memory parallelism. That performance jump removed one of the last practical objections to TypeScript adoption in large monorepos, where slow build times had been the main source of friction.
Real-World Scenarios and Use Cases
The decision between dynamic typing depends on the requirements and characteristics of each project. Here are some real-world scenarios where one approach might be preferred over the other.
Static Typing
In large-scale projects, static typing is often favored as it enables error detection and ensures type safety. It proves beneficial in safety systems like aerospace or medical applications where errors can have severe consequences.
Dynamic Typing
For prototyping and development, dynamic typing is a good choice as it allows developers to iterate quickly without the need for explicit type annotations. It is also favored in situations where data types may change during runtime.
Gradual Typing
Gradual typing works well when a codebase has grown to the point where refactoring without type checks feels risky, but rewriting everything in a statically typed language is off the table. It is also good for teams that use AI coding tools, since adding type hints gives the checker something to work with when reviewing generated code.
BairesDev Engineering Use Case
On the Pinterest engagement, BairesDev scaled a contributing team from 5 engineers in 2019 to 233 engineers by 2023 across a stack spanning Python, Java, Go, Node.js, and React. Coordinating type safety across that polyglot codebase demonstrates why gradual typing and disciplined type checking become increasingly valuable as engineering organizations grow.
As the team expanded across 37 software projects and multiple disciplines, including backend, frontend, data engineering, and QA, consistent type discipline became a practical requirement for keeping refactors safe and onboarding contributors quickly.
Key Takeaways
- Static typing is the right call for large, long-lived, or safety-critical systems.
- Dynamic typing makes sense at the start of a project when the data model is still shifting.
- The static-versus-dynamic framing is increasingly outdated. Most Python and JavaScript teams already use gradual typing without thinking of it that way.
- AI-generated code makes type checking more useful, not less. A 2025 academic study found that 94% of compilation errors in LLM-generated code were type failures.
- TypeScript 7.0 rebuilt its compiler in Go. Builds are roughly 10x faster, which changes the calculus for large monorepos that previously avoided it.


