Repository navigation
Specifying supported TypeScript versions #32166
Description
Activity
I've been wanting this also. Maybe use
enginesfor it also?"engines": { "tsc": "^3.4.0" }Reacted by ehmicky, Daniel, Nicola Dal Maso, Yacine Hmito, Nick Ribal, Stephen Mathieson, Nick Olinger, Dylan Hackworth, jakub791 and Homa WongReacted by ehmicky, Daniel, Yacine Hmito and Dylan HackworthRyanCavanaugh commented
on Jun 28, 2019 MemberMore actionsThis already exists. If your package.json doesn't have a compatible TypeScript version, you'll see
"'package.json' does not have a 'typesVersions' entry that matches version '{0}'."
We decided not to backport the
typesVersionsto prior compiler versions, but the problem will eventually go away once everyone is on a version that supportstypesVersionsRyan Cavanaugh (@RyanCavanaugh) this is great! However this does not seem to work for me. Steps to reproduce:
$ npm install execa
Manually edit (in
node_modules/execa/package.json) the execapackage.jsonto add support only for a future version of TypeScript:"typesVersions": { ">=4": { "*": ["index.d.ts"] } }
Then using
index.ts:import 'execa'
This creates no errors:
$ tsc index.ts
TypeScript
3.5.2, node12.5.0, Ubuntu19.04. Notsconfig.json.RyanCavanaugh commented
on Jun 28, 2019 MemberMore actionsJust to check while you have it set up, does this happen if
index.d.tsis named something else? I think we may have some fallback logicIf I rename
index.d.tstomain.d.ts,tscstill produces no output. I tried renamingindex.jstomain.jsas well.With the original name, the
--traceResolutionoutput is:======== Resolving module 'execa' from '/home/ether/Desktop/index.ts'. ======== Module resolution kind is not specified, using 'NodeJs'. Loading module 'execa' from 'node_modules' folder, target file type 'TypeScript'. Found 'package.json' at '/home/ether/Desktop/node_modules/execa/package.json'. 'package.json' has a 'typesVersions' field with version-specific path mappings. 'package.json' does not have a 'typesVersions' entry that matches version '3.5'. File '/home/ether/Desktop/node_modules/execa.ts' does not exist. File '/home/ether/Desktop/node_modules/execa.tsx' does not exist. File '/home/ether/Desktop/node_modules/execa.d.ts' does not exist. 'package.json' does not have a 'typings' field. 'package.json' does not have a 'types' field. 'package.json' does not have a 'main' field. File '/home/ether/Desktop/node_modules/execa/index.ts' does not exist. File '/home/ether/Desktop/node_modules/execa/index.tsx' does not exist. File '/home/ether/Desktop/node_modules/execa/index.d.ts' exist - use it as a name resolution result. Resolving real path for '/home/ether/Desktop/node_modules/execa/index.d.ts', result '/home/ether/Desktop/node_modules/execa/index.d.ts'. ======== Module name 'execa' was successfully resolved to '/home/ether/Desktop/node_modules/execa/index.d.ts' with Package ID 'execa/index.d.ts@2.0.0'. ========It does fallback to
index.d.ts(which means minimal TypeScript version is not enforced). This is the output when renaming files:======== Resolving module 'execa' from '/home/ether/Desktop/index.ts'. ======== Module resolution kind is not specified, using 'NodeJs'. Loading module 'execa' from 'node_modules' folder, target file type 'TypeScript'. Found 'package.json' at '/home/ether/Desktop/node_modules/execa/package.json'. 'package.json' has a 'typesVersions' field with version-specific path mappings. 'package.json' does not have a 'typesVersions' entry that matches version '3.5'. File '/home/ether/Desktop/node_modules/execa.ts' does not exist. File '/home/ether/Desktop/node_modules/execa.tsx' does not exist. File '/home/ether/Desktop/node_modules/execa.d.ts' does not exist. 'package.json' does not have a 'typings' field. 'package.json' does not have a 'types' field. 'package.json' does not have a 'main' field. File '/home/ether/Desktop/node_modules/execa/index.ts' does not exist. File '/home/ether/Desktop/node_modules/execa/index.tsx' does not exist. File '/home/ether/Desktop/node_modules/execa/index.d.ts' does not exist. File '/home/ether/Desktop/node_modules/@types/execa.d.ts' does not exist. Directory '/home/ether/node_modules' does not exist, skipping all lookups in it. Directory '/home/node_modules' does not exist, skipping all lookups in it. Directory '/node_modules' does not exist, skipping all lookups in it. Loading module 'execa' from 'node_modules' folder, target file type 'JavaScript'. Found 'package.json' at '/home/ether/Desktop/node_modules/execa/package.json'. 'package.json' has a 'typesVersions' field with version-specific path mappings. 'package.json' does not have a 'typesVersions' entry that matches version '3.5'. File '/home/ether/Desktop/node_modules/execa.js' does not exist. File '/home/ether/Desktop/node_modules/execa.jsx' does not exist. 'package.json' does not have a 'main' field. File '/home/ether/Desktop/node_modules/execa/index.js' does not exist. File '/home/ether/Desktop/node_modules/execa/index.jsx' does not exist. Directory '/home/ether/node_modules' does not exist, skipping all lookups in it. Directory '/home/node_modules' does not exist, skipping all lookups in it. Directory '/node_modules' does not exist, skipping all lookups in it. ======== Module name 'execa' was not resolved. ========It does not resolve
execabut does not create any error messages.Here's one thing you can try:
- Add a
notsupported.d.tsfile toexeca. - Modify the package.json for
execain the following way:
"types": "notsupported.d.ts", "typesVersions": { ">=3.4.0-0": { "*": ["index.d.ts"] } }TypeScript versions earlier than 3.4 will load
notsupported.d.tswhich is empty. TypeScript versions for 3.4 onward will loadindex.d.ts. Attempting toimport {} from 'execa'will report an error sincenotsupported.d.tsis not a module. However,import 'execa'will still work without error because this import form only imports the referenced file for side-effects and does not care whether the referenced file is a module.Reacted by ehmicky- Add a
Thanks for this tip Ron Buckton (@rbuckton)! It works but some issues with this approach could be:
- the error message doesn't make it clear for the user that they are using an unsupported TypeScript version:
File '/home/ether/Desktop/node_modules/execa/notsupported.d.ts' is not a module.. Many users will probably end up still creating GitHub issues thinking there's something wrong with the types declarations. - it requires creating an empty file, although that's not a big issue.
More generally speaking this would be more of a workaround. Most TypeScript projects probably have a minimal supported TypeScript version, so it might be beneficial to have a "standard" way to specify it. This could also enable tools (linters, static analysis tools) to use it, in the same way that
engines.nodeis currently used for Node.js versions.- the error message doesn't make it clear for the user that they are using an unsupported TypeScript version:
If we were to add a feature to disallow older versions of TypeScript, it wouldn't catch TS versions prior to the version where the feature was introduced.
It's not pretty, but another workaround would be to introduce a type error that could provide some context to the users that the TS version they are using isn't supported. Something like:
// notsupported.d.ts type __Check<T extends ">= 3.6.1"> = T; type __NotSupported = __Check<"This version of TypeScript">; // error: Type '"This version of TypeScript"' does not satisfy the constraint '">= 3.6.1"'.
Thanks Ron Buckton (@rbuckton)! That does provide with a better error message, so this seems like the best workaround at the moment.
Any feature related to this issue would indeed only work for users whose TS version is
>=to the version that introduced that feature. I think this might still be a good idea even if it would take some time to be useful (since it requires most TypeScript users to migrate to at least that TS version first, which might take years).As a side note, I think the following might work as well, as a slight variation of the workaround above, maybe more explicit:
"typesVersions": { ">=3.4.0-0": { "*": ["index.d.ts"] }, "*": { "*": ["notsupported.d.ts"] } }
Keep in mind that won't catch TypeScript 3.0 and earlier
Reacted by ehmicky27 remaining items
- addedDeclinedThe issue was declined as something which matches the TypeScript visionThe issue was declined as something which matches the TypeScript visionSuggestionAn idea for TypeScriptAn idea for TypeScriptand removedBugA bug in TypeScriptA bug in TypeScriptRescheduledThis issue was previously scheduled to an earlier milestoneThis issue was previously scheduled to an earlier milestone
on Feb 4, 2022 RyanCavanaugh commented
on Feb 4, 2022 MemberMore actionsThis can has been getting kicked down the road for quite a while and it seems like this isn't enough of a problem in practice to warrant a capital-f Feature for it. It's pretty straightforward at this point to have a pre-minumum-tagged file with the content
// @ts-expect-error type RequiredTypeScriptVersion = "3.8";
which would be sufficient for people to figure out what's going on.
I understand. Thanks Ryan Cavanaugh (@RyanCavanaugh) for explaining the rational behind this decision and for providing a workaround. 👍
Has anyone implemented this approach? I can't seem to get it to officially work and wanted to see a working example if anyone has one.
Has anyone implemented this approach? I can't seem to get it to officially work and wanted to see a working example if anyone has one.
Steve Ayers (@smaye81) I implemented it in
graphql-js, see here:
https://github.com/graphql/graphql-js/blob/743f42b6ef6006d35bf9e0b45e3b70d6e9100596/resources/build-npm.ts#L86-L97
It produces an error like this:node_modules/graphql/NotSupportedTSVersion.d.ts:1:63 - error TS1003: Identifier expected. 1 "Package 'graphql' support only TS versions that are >=4.4.0".Has anyone implemented this approach? I can't seem to get it to officially work and wanted to see a working example if anyone has one.
Steve Ayers (@smaye81) I implemented it in
graphql-js, see here: https://github.com/graphql/graphql-js/blob/743f42b6ef6006d35bf9e0b45e3b70d6e9100596/resources/build-npm.ts#L86-L97 It produces an error like this:node_modules/graphql/NotSupportedTSVersion.d.ts:1:63 - error TS1003: Identifier expected. 1 "Package 'graphql' support only TS versions that are >=4.4.0".Great thank you Ivan Goncharov (@IvanGoncharov) !
Search Terms
version
minimal version
minimum version
typesVersions
Suggestion
Specifying the minimal TypeScript version supported by a project.
With
typesVersions, fallbacks can be specified for earlier versions. But we cannot specify which earlier versions are not supported.Use Cases
Better error reporting for users using older TypeScript versions.
Examples
execatypes only support TypeScript>= 3.4because of how thereadonlykeyword is used.There should be a way for us to specify this. One way would be to extend the
typesVersionsfield to add this feature.Our users would then get a clear error message similar to the one produced by the
engines.nodefield for Node.js versions. Instead at the moment, we get GitHub issues from users using older TypeScript versions.Checklist
My suggestion meets these guidelines: