Security News
JSR Working Group Kicks Off with Ambitious Roadmap and Plans for Open Governance
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
downlevel-dts
Advanced tools
The downlevel-dts npm package is used to downlevel TypeScript declaration files (.d.ts) to an older version of TypeScript. This is useful for library authors who want to support older versions of TypeScript without maintaining multiple versions of their codebase.
Downlevel TypeScript Declarations
This feature allows you to downlevel TypeScript declaration files to a specified TypeScript version. In this example, the input .d.ts file is downleveled to TypeScript version 3.7 and written to the output file.
const downlevelDts = require('downlevel-dts');
const fs = require('fs');
const inputFilePath = 'path/to/input.d.ts';
const outputFilePath = 'path/to/output.d.ts';
const inputDts = fs.readFileSync(inputFilePath, 'utf8');
const outputDts = downlevelDts(inputDts, '3.7');
fs.writeFileSync(outputFilePath, outputDts);
The TypeScript package itself can be used to generate declaration files, but it does not provide functionality to downlevel existing declaration files. It is more focused on compiling TypeScript code to JavaScript and generating .d.ts files from TypeScript source code.
API Extractor is a tool for managing and analyzing the public API surface of a TypeScript library. While it provides features for generating and validating .d.ts files, it does not specifically focus on downleveling them to older TypeScript versions.
dts-bundle-generator is a tool for generating a single .d.ts file from a TypeScript project. It focuses on bundling multiple declaration files into one, rather than downleveling existing declaration files.
downlevel-dts rewrites .d.ts files created by any version of Typescript so that they work with Typescript 3.4 or later. It does this by converting code with new features into code that uses equivalent old features. For example, it rewrites accessors to properties, because Typescript didn't support accessors in .d.ts files until 3.6:
declare class C {
get x(): number;
}
becomes
declare class C {
readonly x: number;
}
Here is the list of features that are downlevelled:
Omit
(3.5)type Less = Omit<T, K>;
becomes
type Less = Pick<T, Exclude<keyof T, K>>;
Omit
has had non-builtin implementations since Typescript 2.2, but
became built-in in Typescript 3.5.
Omit
is a type alias, so the downlevel should behave exactly the same.
Typescript prevented accessors from being in .d.ts files until Typescript 3.6 because they behave very similarly to properties. However, they behave differently with inheritance, so the distinction can be useful.
declare class C {
get x(): number;
}
becomes
declare class C {
readonly x: number;
}
The properties emitted downlevel can be overridden in more cases than the original accessors, so the downlevel d.ts will be less strict. See the Typescript 3.7 release notes for more detail.
asserts
assertion guards (3.7)Typescript 3.7 introduced the asserts
keyword, which provides a way to indicate that a function will throw if a parameter doesn't meet a condition.
This allows Typescript to understand that whatever condition such a function checks must be true for the remainder of the containing scope.
Since there is no way to model this before 3.7, such functions are downlevelled to return void
:
declare function assertIsString(val: any, msg?: string): asserts val is string;
declare function assert(val: any, msg?: string): asserts val;
becomes
declare function assertIsString(val: any, msg?: string): void;
declare function assert(val: any, msg?: string): void;
The downlevel emit is quite simple:
import type { T } from 'x';
becomes
import { T } from "x";
The downlevel d.ts will be less strict because a class will be constructable:
declare class C {
}
export type { C };
becomes
declare class C {}
export { C };
and the latter allows construction:
import { C } from "x";
var c = new C();
#private
(3.8)Typescript 3.8 supports the new ECMAScript-standard #private properties in addition to its compile-time-only private properties. Since neither are accessible at compile-time, downlevel-dts converts #private properties to compile-time private properties:
declare class C {
#private
}
It becomes:
declare class C {
private "#private"`
}
The standard emit for any class with a #private property just adds a
single #private
line. Similarly, a class with a private property
adds only the name of the property, but not the type. The d.ts
includes only enough information for consumers to avoid interfering
with the private property:
class C {
#x = 1
private y = 2
}
emits
declare class C {
#private
private y
}
which then downlevels to
declare class C {
private "#private";
private y;
}
This is incorrect if your class already has a field named "#private"
.
But you really shouldn't do this!
The downlevel d.ts incorrectly prevents consumers from creating a
private property themselves named "#private"
. The consumers of the
d.ts also shouldn't do this.
export * from 'x'
(3.8)Typescript 3.8 supports the new ECMAScript-standard export * as namespace
syntax, which is just syntactic sugar for two import/export
statements:
export * as ns from 'x';
becomes
import * as ns_1 from "x";
export { ns_1 as ns };
The downlevel semantics should be exactly the same as the original.
Since the earliest downlevel feature is from Typescript 3.5, downlevel-dts targets Typescript 3.4. In the future the downlevel target may be configurable as Typescript 3.4 becomes less used.
Currently, Typescript 3.0 features like unknown
are not
downlevelled, nor are there any other plans to support Typescript 2.x.
$ npm install downlevel-dts
$ npx downlevel-dts . ts3.4
"typesVersions": {
"<3.8": { "*": ["ts3.4/*"] }
}
$ cp tsconfig.json ts3.4/tsconfig.json
These instructions are modified and simplified from the Definitely Typed.
FAQs
Convert d.ts to be compatible with older typescript compilers
We found that downlevel-dts demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Security News
Research
An advanced npm supply chain attack is leveraging Ethereum smart contracts for decentralized, persistent malware control, evading traditional defenses.
Security News
Research
Attackers are impersonating Sindre Sorhus on npm with a fake 'chalk-node' package containing a malicious backdoor to compromise developers' projects.