Search Terms
typesVersions, 3.1
Problem
Using an unordered object for the typesVersion setting in package.json is brittle as the implementation depends on the behavior of JSON.parse and how keys in an object are iterated over.
FWIW, using an object made sense before version ranges support was added to typesVersion.
Suggestion
Change typesVersions setting package.json to use an (ordered) array of configurations rather than an (unordered) object. For example:
{
"typesVersions": [{
"version": ">=3.2",
"paths": { "*": ["ts3.2/*"] }
}, {
"version": ">=3.1",
"paths": { "*": ["ts3.1/*"] }
}
]
}
Alternatively, you could keep the current format, but remove the ambiguity by disallowing overlapping version matches. So the example in the 3.1 docs would be invalid and treated as error when compiling under TypeScript 3.2. A corresponding valid configuration would look like this:
"typesVersion": {
// NOTE: order doesn't matter :-)
">=3.1 <3.2": { "*": ["ts3.1/*"] },
">=3.2": { "*": ["ts3.2/*"] }
}
This would require getPackageJsonTypesVersionsPaths in src/compiler/moduleNameResolver.ts to check all the typesVersion configs and throw an error if there is more than one match for the current TypeScript version.
Backwards Compatibility
For backwards compatibility of an array configuration, the 3.1 object configuration could still be supported, but should be deprecated.
More Info
The JSON specification says that:
An object is an unordered set of name/value pairs.
However, the typesVersions setting in TypeScript 3.1 treats it as an order set. From the docs:
Since ranges have the potential to overlap, determining which redirect applies is order-specific. That means in the above example, even though both the >=3.2 and the >=3.1 matchers support TypeScript 3.2 and above, reversing the order could have different behavior, so the above sample would not be equivalent to the following.
{
"name": "package-name",
"version": "1.0",
"types": "./index.d.ts",
"typesVersions": {
// NOTE: this doesn't work!
">=3.1": { "*": ["ts3.1/*"] },
">=3.2": { "*": ["ts3.2/*"] }
}
}
Use Cases
- Removes dependency on undocumented object key iteration order
- Won't won't be affected by someone sorting their
package.json keys (and subkeys).
Checklist
My suggestion meets these guidelines:
Search Terms
typesVersions, 3.1
Problem
Using an unordered object for the
typesVersionsetting inpackage.jsonis brittle as the implementation depends on the behavior ofJSON.parseand how keys in an object are iterated over.FWIW, using an object made sense before version ranges support was added to
typesVersion.Suggestion
Change
typesVersionssettingpackage.jsonto use an (ordered) array of configurations rather than an (unordered) object. For example:Alternatively, you could keep the current format, but remove the ambiguity by disallowing overlapping version matches. So the example in the 3.1 docs would be invalid and treated as error when compiling under TypeScript 3.2. A corresponding valid configuration would look like this:
This would require
getPackageJsonTypesVersionsPathsinsrc/compiler/moduleNameResolver.tsto check all thetypesVersionconfigs and throw an error if there is more than one match for the current TypeScript version.Backwards Compatibility
For backwards compatibility of an array configuration, the 3.1 object configuration could still be supported, but should be deprecated.
More Info
The JSON specification says that:
However, the
typesVersionssetting in TypeScript 3.1 treats it as an order set. From the docs:Use Cases
package.jsonkeys (and subkeys).Checklist
My suggestion meets these guidelines: