TypeScript 4.5: что нового
Разработчики представили TypeScript 4.5. В новой версии поработали над производительностью языка, добавили новые возможности автодополнения кода для редакторов и упростили способы переподключения библиотек.
при обновлении TypeScript необходимо вручную внести изменения в файлы объединений;
сами файлы относительно тяжело настроить в соответствии с потребностями проекта.
Затем уже можно обратиться к диспетчеру для того, чтобы установить пакет, который заменит библиотеку. К примеру, вместе с новой версией TypeScript разработчики опубликовали версии API-интерфейсов DOM на @types/web и для привязки проекта к определенной версии DOM-интерфейса достаточно добавить в package.json следующие строчки:
После этого можно спокойно обновлять TypeScript и не бояться потерять необходимые зависимости.
Также в TypeScript 4.5 теперь можно сузить значения строк шаблона и установить использовать их в качестве дискриминанта. К примеру, следующий отрывок кода не корректно исполнялся в прошлых версиях, но сейчас спокойно проходит проверку типов:
В новой версии реализовали механизм устранения хвостовой рекурсии при вызове условных типов. Известно, что TypeScript прекращает выполнение кода, если обнаруживает бесконечную рекурсию или расширение типов с множественной промежуточной генерацией результатов. За примером обратимся к следующему отрывку кода. В данном случае тип TrimLeft удаляет пробелы в начале строки — если обнаружена строка с пробелом в начале, то оставшаяся часть строки передается обратно в TrimLeft :
И все будет работать, но если вдруг строка будет содержать в начале 50 пробелов, то при выполнении выйдет ошибка:
Все дело в том, что TrimLeft написан с использованием хвостовой рекурсии в одной ветке. Когда тип вызывает сам себя, то возвращает результат и ничего с ним не делает. Поскольку таким типам не требуется создавать промежуточные результаты, то их можно реализовать быстрее. Именно поэтому в TypeScript 4.5 устранили хвостовую рекурсию для условных типов — пока одна ветвь условного типа является просто другим условным типом, TypeScript может избегать промежуточные результаты.
В некоторых случаях TypeScript не может точно определить используется ли импорт в коде. К примеру, следующий отрывок кода будет по умолчанию удален:
Также TypeScript 4.5 поддерживает предложение ECMAScript для проверки на факт того, есть ли у объекта приватные поля. Теперь можно создать класс с элементом поля #private и посмотреть, есть ли у другого объекта такое же поле с помощью оператора in :
Кроме всех прочих обновлений синтаксиса, TypeScript теперь на всех ОС поддерживает функцию realpathSync.native в Node.js. Раньше эта функция была доступна только в Linux. Теперь же, если у пользователя установлена последняя версия Node.js, то компилятор будет использовать эту функцию в Windows и macOS. Этот шаг помог ускорить загрузку проектов на 5-13%.
В версии 4.5 представили новые виды автодополнения кода. Первый относится к завершению фрагментов методов и класса. Теперь при реализации метода в подклассе TypeScript автоматически дополняет не только имя метода, но и полную подпись и фигурные скобки для тела. При этом курсор сразу перемещается в тело метода.
Автодополнение методов в подклассе
Второй тип автодополнения относится к фрагментам JSX-атрибутов. Теперь при записи атрибута в JSX-тег TypeScript предложит несколько готовых вариантов и разместит курсор в нужном месте. Это поможет сэкономить немного времени при наборе кода.
Автодополнение JSX-тегов
«Наконец-то!»: в TypeScript 4.4 появилась долгожданная функция
Редактор новостей Highload
Отмена ограничений для Symbol, статические блоки в классах и многое другое. Microsoft выпустила новую версию языка программирования TypeScript 4.4. В очередной сборке наконец-то появилась долгожданная разработчиками функция. Какая именно — читайте далее.
Основные новшества TypeScript 4.4
Control Flow Analysis псевдонимов условий и дискриминант
Теперь так называемые type guards будут использовать control flow analysis для выяснения типов во всех языковых структурах. Можно выносить «type guards» как отдельные переменные.
Отмена ограничений для Symbol и Template String Pattern Index Signature
Одна из самых долгожданных разработчикам фич наконец-то появилась в TypeScript. До сих пор индексные подписи были ограничены строчными и числовыми ключами, а в языке нельзя было индексировать объекты с помощью символьных ключей. Также нельзя было моделировать индексную сигнатуру некоторого подмножества строчных ключей.
В новой версии TypeScript сняли эти ограничения. Теперь можно индексировать подписи для символов и шаблонов строк.
Unknown Type в Catch Variables используется по умолчанию
Статические блоки в классах
Версия TypeScript 4.4 обеспечивает поддержку блоков static в классах . Это предстоящая функция ECMAScript, которая позволяет писать более сложный код инициализации для статических членов.
Inlay Hints
Примечание: в настройках Visual Studio Code можно изменить время и место показа подсказок.
Подсказки по написанию кода для JavaScript
Теперь TypeScript выдает предложения по правописанию в простых файлах JavaScript без // @ts-check или с выключенным checkJs в проекте.
Обновления и улучшения —help
Автоимпорт показывает фактические пути к Completion Lists
В новой версии completion item label теперь показывает фактически путь к модулю, который будет использоваться для импорта.
Из плюсов разработчики также выделяют изменения QoL и повышение производительности.
Announcing TypeScript 4.0
Today we are thrilled to announce the availability of TypeScript 4.0! This version of the language represents our next generation of TypeScript releases, as we dive deeper into expressivity, productivity, and scalability.
If you’re not familiar with TypeScript, it’s a language that builds on top of JavaScript by adding syntax for static types. The idea is that by writing down the types of your values and where they’re used, you can use TypeScript to type-check your code and tell you about mistakes before you run your code (and even before saving your file). You can then use the TypeScript compiler to then strip away types from your code, and leaving you with clean, readable JavaScript that runs anywhere. Beyond checking, TypeScript also uses static types to power great editor tooling like auto-completion, code navigation, refactorings, and more. In fact, if you’ve used JavaScript in an editor like Visual Studio Code or Visual Studio, you’ve already been using an experience powered by types and TypeScript. You can learn more about all of this on our website.
With TypeScript 4.0, there are no major breaking changes. In fact, if you’re new to the language, now is the best time to start using it. The community is already here and growing, with working code and great new resources to learn. And one thing to keep in mind: despite all the good stuff we’re bringing in 4.0, you really only need to know the basics of TypeScript to be productive!
If you’re already using TypeScript in your project, you can either get it through NuGet or use npm with the following command:
You can also get editor support by
The 4.0 Journey
TypeScript is a core part of many people’s JavaScript stack today. On npm, TypeScript saw over 50 million monthly downloads for the first time in July! And while we recognize there’s always room for growth and improvement, it’s clear that most people coding in TypeScript really do enjoy it. StackOverflow’s most recent developer survey pins TypeScript as the 2nd most-loved language. In the most recent State of JS Survey, around 89% of developers who used TypeScript said that they would use it again.
It’s worth digging a bit into how we got here. In our past two major versions, we looked back at some highlights that shined over the years. For TypeScript 4.0, we’re going to keep up that tradition.
TypeScript 3.1 extended the capabilities of mapped types to work on tuple and array types, and made it dramatically easier to attach properties to functions without resorting to TypeScript-specific runtime features that have fallen out of use.
With TypeScript 3.5 and 3.6, we saw some tightening up of the type system rules, along with smarter compatibility checking rules.
TypeScript 3.7 was a very noteworthy release because it featured a rich combination of new type system features with ECMAScript features. From the type-system side, we saw recursive type alias references and support for assertion-style functions, both which are unique type-system features. From the JavaScript side, the release brought optional chaining and coalescing, two of the most highly demanded features for TypeScript and JavaScript users alike, championed in TC39 in part by our team.
Much more recently, 3.8 and 3.9 have brought type-only imports/exports, along with ECMAScript features like private fields, top-level await in modules, and new export * syntaxes. These releases also delivered performance and scalability optimizations.
We haven’t even touched on all the work in our language service, our infrastructure, our website, and other core projects which are incredibly valuable to the TypeScript experience. Beyond the core team’s projects is the incredible community of contributors in the ecosystem, pushing the experience forward, and helping out with DefinitelyTyped and even TypeScript itself. DefinitelyTyped had just 80 pull requests in 2012 when it first started, picking up on the tail end of the year. In 2019, it had over 8300 pull requests, which still astounds us. These contributions are fundamental to the TypeScript experience, so we’re grateful for such a bustling and eager community that’s been improving the ecosystem and pushed us to constantly improve.
What’s New?
All this brings us to 4.0! So, without further ado, let’s dive into what’s new!
Variadic Tuple Types
Consider a function in JavaScript called concat that takes two array or tuple types and concatenates them together to make a new array.
How would we type either of these in TypeScript?
Uh…okay, that’s…seven overloads for when the second array is always empty. Let’s add some for when arr2 has one argument.
This is another case of what we like to call “death by a thousand overloads”, and it doesn’t even solve the problem generally. It only gives correct types for as many overloads as we care to write. If we wanted to make a catch-all case, we’d need an overload like the following:
But that signature doesn’t encode anything about the lengths of the input, or the order of the elements, when using tuples.
TypeScript 4.0 brings two fundamental changes, along with inference improvements, to make typing these possible.
The first change is that spreads in tuple type syntax can now be generic. This means that we can represent higher-order operations on tuples and arrays even when we don’t know the actual types we’re operating over. When generic spreads are instantiated (or, replaced with a real type) in these tuple types, they can produce other sets of array and tuple types.
The second change is that rest elements can occur anywhere in a tuple – not just at the end!
Previously, TypeScript would issue an error like the following:
But with TypeScript 4.0, this restriction is relaxed.
Note that in cases when we spread in a type without a known length, the resulting type becomes unbounded as well, and all the following elements factor into the resulting rest element type.
By combining both of these behaviors together, we can write a single well-typed signature for concat :
While that one signature is still a bit lengthy, it’s just one signature that doesn’t have to be repeated, and it gives predictable behavior on all arrays and tuples.
TypeScript 4.0 improves the inference process for rest parameters and rest tuple elements so that we can type this and have it “just work”.
In this case, partialCall understands which parameters it can and can’t initially take, and returns functions that appropriately accept and reject anything left over.
Variadic tuple types enable a lot of new exciting patterns, especially around function composition. We expect we may be able to leverage it to do a better job type-checking JavaScript’s built-in bind method. A handful of other inference improvements and patterns also went into this, and if you’re interested in learning more, you can take a look at the pull request for variadic tuples.
Labeled Tuple Elements
Improving the experience around tuple types and parameter lists is important because it allows us to get strongly typed validation around common JavaScript idioms – really just slicing and dicing argument lists and passing them to other functions. The idea that we can use tuple types for rest parameters is one place where this is crucial.
For example, the following function that uses a tuple type as a rest parameter…
…should appear no different from the following function…
There is one place where the differences begin to become observable though: readability. In the first example, we have no parameter names for the first and second elements. While these have no impact on type-checking, the lack of labels on tuple positions can make them harder to use – harder to communicate our intent.
That’s why in TypeScript 4.0, tuples types can now provide labels.
To deepen the connection between parameter lists and tuple types, the syntax for rest elements and optional elements mirrors the syntax for parameter lists.
There are a few rules when using labeled tuples. For one, when labeling a tuple element, all other elements in the tuple must also be labeled.
It’s worth noting – labels don’t require us to name our variables differently when destructuring. They’re purely there for documentation and tooling.
Overall, labeled tuples are handy when taking advantage of patterns around tuples and argument lists, along with implementing overloads in a type-safe way. In fact, TypeScript’s editor support will try to display them as overloads when possible.
To learn more, check out the pull request for labeled tuple elements.
Class Property Inference from Constructors
TypeScript 4.0 can now use control flow analysis to determine the types of properties in classes when noImplicitAny is enabled.
Short-Circuiting Assignment Operators
JavaScript, and a lot of other languages, support a set of operators called compound assignment operators. Compound assignment operators apply an operator to two arguments, and then assign the result to the left side. You may have seen these before:
These operators are great for substituting any example where a user might write code like the following:
Or a similar if block like
There are even some patterns we’ve seen (or, uh, written ourselves) to lazily initialize values, only if they’ll be needed.
(look, we’re not proud of all the code we write…)
On the rare case that you use getters or setters with side-effects, it’s worth noting that these operators only perform assignments if necessary. In that sense, not only is the right side of the operator “short-circuited” – the assignment itself is too.
Try running the following example to see how that differs from always performing the assignment.
We’d like to extend a big thanks to community member Wenlu Wang for this contribution!
unknown on catch Clause Bindings
The above has some undesirable behavior if we’re trying to prevent more errors from happening in our error-handling code! Because these variables have the type any by default, they lack any type-safety which could have errored on invalid operations.
That’s why TypeScript 4.0 now lets you specify the type of catch clause variables as unknown instead. unknown is safer than any because it reminds us that we need to perform some sorts of type-checks before operating on our values.
Custom JSX Factories
When using JSX, a fragment is a type of JSX element that allows us to return multiple child elements. When we first implemented fragments in TypeScript, we didn’t have a great idea about how other libraries would utilize them. Nowadays most other libraries that encourage using JSX and support fragments have a similar API shape.
In TypeScript 4.0, users can customize the fragment factory through the new jsxFragmentFactory option.
In cases where you need to have a different JSX factory on a per-file basis, you can take advantage of the new /** @jsxFrag */ pragma comment. For example, the following…
…will get transformed to this output JavaScript…
We’d like to extend a big thanks to community member Noj Vek for sending this pull request and patiently working with our team on it.
You can see that the pull request for more details!
Editor Improvements
The TypeScript compiler doesn’t only power the editing experience for TypeScript itself in most major editors – it also powers the JavaScript experience in the Visual Studio family of editors and more. For that reason, much of our work focuses on improving editor scenarios – the place you spend most of your time as a developer.
Using new TypeScript/JavaScript functionality in your editor will differ depending on your editor, but
You can check out a partial list of editors that have support for TypeScript to learn more about whether your favorite editor has support to use new versions.
Convert to Optional Chaining
Optional chaining is a recent feature that’s received a lot of love. That’s why TypeScript 4.0 brings a new refactoring to convert common patterns to take advantage of optional chaining and nullish coalescing!
Keep in mind that while this refactoring doesn’t perfectly capture the same behavior due to subtleties with truthiness/falsiness in JavaScript, we believe it should capture the intent for most use-cases, especially when TypeScript has more precise knowledge of your types.
/** @deprecated */ Support
This new functionality is available thanks to Wenlu Wang. See the pull request for more details.
Partial Semantic Mode at Startup
We’ve heard a lot from users suffering from long startup times, especially on bigger projects. The culprit is usually a process called program construction. This is the process of starting with an initial set of root files, parsing them, finding their dependencies, parsing those dependencies, finding those dependencies’ dependencies, and so on. The bigger your project is, the longer you’ll have to wait before you can get basic editor operations like go-to-definition or quick info.
That’s why we’ve been working on a new mode for editors to provide a partial experience until the full language service experience has loaded up. The core idea is that editors can run a lightweight partial server that only looks at the current files that the editor has open.
It’s hard to say precisely what sorts of improvements you’ll see, but anecdotally, it used to take anywhere between 20 seconds to a minute before TypeScript would become fully responsive on the Visual Studio Code codebase. In contrast, our new partial semantic mode seems to bring that delay down to just a few seconds. As an example, in the following video, you can see two side-by-side editors with TypeScript 3.9 running on the left and TypeScript 4.0 running on the right.
When restarting both editors on a particularly large codebase, the one with TypeScript 3.9 can’t provide completions or quick info at all. On the other hand, the editor with TypeScript 4.0 can immediately give us a rich experience in the current file we’re editing, despite loading the full project in the background.
Currently the only editor that supports this mode is Visual Studio Code which has some UX improvements coming up in Visual Studio Code Insiders. We recognize that this experience may still have room for polish in UX and functionality, and we have a list of improvements in mind. We’re looking for more feedback on what you think might be useful.
Smarter Auto-Imports
Auto-import is a fantastic feature that makes coding a lot easier; however, every time auto-import doesn’t seem to work, it can throw users off a lot. One specific issue that we heard from users was that auto-imports didn’t work on dependencies that were written in TypeScript – that is, until they wrote at least one explicit import somewhere else in their project.
Why would auto-imports work for @types packages, but not for packages that ship their own types? It turns out that auto-imports only work on packages your project already includes. Because TypeScript has some quirky defaults that automatically add packages in node_modules/@types to your project, those packages would be auto-imported. On the other hand, other packages were excluded because crawling through all your node_modules packages can be really expensive.
All of this leads to a pretty lousy getting started experience for when you’re trying to auto-import something that you’ve just installed but haven’t used yet.
TypeScript 4.0 now does a little extra work in editor scenarios to include the packages you’ve listed in your package.json ‘s dependencies (and peerDependencies ) fields. The information from these packages is only used to improve auto-imports, and doesn’t change anything else like type-checking. This allows us to provide auto-imports for all of your dependencies that have types, without incurring the cost of a complete node_modules search.
In the rare cases when your package.json lists more than ten typed dependencies that haven’t been imported yet, this feature automatically disables itself to prevent slow project loading. To force the feature to work, or to disable it entirely, you should be able to configure your editor. For Visual Studio Code, this is the “Include Package JSON Auto Imports” (or typescript.preferences.includePackageJsonAutoImports ) setting.

Our New Website!
The TypeScript website has recently been rewritten from the ground up and rolled out!
We already wrote a bit about our new site, so you can read up more there; but it’s worth mentioning that we’re still looking to hear what you think! If you have questions, comments, or suggestions, you can file them over on the website’s issue tracker.
Breaking Changes
lib.d.ts Changes
Properties Overriding Accessors (and vice versa) is an Error
Previously, it was only an error for properties to override accessors, or accessors to override properties, when using useDefineForClassFields ; however, TypeScript now always issues an error when declaring a property in a derived class that would override a getter or setter in the base class.
Operands for delete must be optional.
Usage of TypeScript’s Node Factory is Deprecated
Today TypeScript provides a set of “factory” functions for producing AST Nodes; however, TypeScript 4.0 provides a new node factory API. As a result, for TypeScript 4.0 we’ve made the decision to deprecate these older functions in favor of the new ones.
What’s Next?
You’ve reached the end of this release post, but luckily there’s more coming. TypeScript 4.1’s iteration plan is already up so you can get a sense of what’s on the horizon. In the meantime, you can give new features in 4.1 a shot by using nightly builds in your workspace, or maybe just in your editor. Whether you’re on TypeScript 4.0, or the next version, we’re interested in hearing feedback! Feel free to leave a comment below, reach out over Twitter, or file an issue on GitHub.
We said it once, and we’ll say it again: we owe so much to our community for all their work and dedication. In turn, we want to making coding in TypeScript and JavaScript the pure joy you deserve. This involves not just focusing on one thing, but a combination of improving the language and editing experience, keeping an eye on speed, iterating on our UX, smoothing the onboarding and learning experience as a whole, and more.
Thank you so much, and enjoy 4.0!
– Daniel Rosenwasser and the TypeScript Team






