May 07, 2021 TypeScript
In TypeScript 3.1, the type of mapped object on the yuan and array now produces a new binary/array instead of creating a new type in which
push()
pop()
length
are converted.
For example:
type MapToPromise<T> = { [K in keyof T]: Promise<T[K]> };
type Coordinate = [number, number]
type PromiseCoordinate = MapToPromise<Coordinate>; // [Promise<number>, Promise<number>]
MapToPromise
uses a type
T
which converts only numeric
Coordinate
a group, such as a Control. I
n
[number, number]
are two number-named properties:
0
1
W
hen such a metagroup is given,
MapToPromise
a new metagroup
0
1
are the original type
Promise
s.
As a result,
PromiseCoordinate
ends up with the
[Promise<number>, Promise<number>]
TypeScript 3.1 defines
const
on function declarations and const-declared functons, simply assigning the properties of those functions within the same range. T
his allows us to write the javaScript code of the specification without resorting
namespace
For example:
function readImage(path: string, callback: (err: any, image: Image) => void) {
// ...
}
readImage.sync = (path: string) => {
const contents = fs.readFileSync(path);
return decodeImageSync(contents);
}
Here, we have a readImage function that reads images in a
readImage
manner.
In
readImage
readImage
a convenient function called
readImage.sync
While ECMAScript export is often a better way to provide this functionality, this new support allows code written with this style to "just work" typeScript.
In addition, this property declaration approach allows us to express common patterns, such as
defaultProps
and
propTypes
export const FooComponent => ({ name }) => (
<div>Hello! I am {name}</div>
);
FooComponent.defaultProps = {
name: "(anonymous)",
};
More specifically, the erstological mapping type is similar to the form above.
Feedback from the community and related experience tell us that it is difficult to accommodate older versions of users while taking advantage of the latest TypeScript features.
TypeScript introduces a new feature
typesVersions
to help meet these scenarios.
When you use node module resolution in TypeScript 3.1, when TypeScript cracks open
package.json
determine which files need to be read, it first looks at a new field
typesVersions
package.json
with the
typesVersions
field might look like this:
{
"name": "package-name",
"version": "1.0",
"types": "./index.d.ts",
"typesVersions": {
">=3.1": { "*": ["ts3.1/*"] }
}
}
This
package.json
TypeScript to check if the current version of TypeScript is running. I
f it is 3.1 or later, it calculates your path relative to the package import and
ts3.1
folder.
That's what the meaning of
{ "*": ["ts3.1/*"] }
So, in the example above, if we
"package-name"
and run in TypeScript 3.1, we'll try to
[...]/node_modules/package-name/ts3.1/index.d.ts
(and other related paths) resolution. I
f we
package-name/foo
we'll try to
[...]/node_modules/package-name/ts3.1/foo.d.ts
and
[...]/node_modules/package-name/ts3.1/foo/index.d.ts
。
What if we don't run in TypeScript 3.1 in this example? W
ell, if there are no matching fields in
typesVersions
TypeScript will fall back to
types
field, so TypeScript 3.0 and earlier will be redirected to .
[...]/node_modules/package-name/index.d.ts
。
TypeScript determines whether the compiler and language version match by using Node's semver range.
typesVersions
support multiple fields, each of which is specified by the range to match.
{
"name": "package-name",
"version": "1.0",
"types": "./index.d.ts",
"typesVersions": {
">=3.2": { "*": ["ts3.2/*"] },
">=3.1": { "*": ["ts3.1/*"] }
}
}
Because the ranges may overlap, determine which redirects are applied that are order-specific.
This means that in
>=3.2
the example above, the inverse order may behave differently, even if both the matchers are typeScript 3.2 and
>=3.1
so the above example is not equivalent to the following example:
{
"name": "package-name",
"version": "1.0",
"types": "./index.d.ts",
"typesVersions": {
// NOTE: this doesn't work!
">=3.1": { "*": ["ts3.1/*"] },
">=3.2": { "*": ["ts3.2/*"] }
}
}