downlevel-dts
Advanced tools
Comparing version
@@ -24,2 +24,14 @@ /// <reference path="./src/test.d.ts" /> | ||
import { C as CD } from "./src/test"; | ||
/*preserve it */ | ||
import { C as CD2, C as CD3 } from "./src/test"; | ||
/*this too */ | ||
import { C as CD4, C as CD5 } from "./src/test"; | ||
/*preserve it */ | ||
export { CD2, CD3 }; | ||
/*this too */ | ||
export { CD4, CD5 }; | ||
/*preserve it */ | ||
export { C as CD6, C as CD7 } from "./src/test"; | ||
/*this too */ | ||
export { C as CD8, C as CD9 } from "./src/test"; | ||
import * as rex_1 from "./src/test"; | ||
@@ -26,0 +38,0 @@ //another comment |
@@ -24,2 +24,14 @@ /// <reference path="./src/test.d.ts" /> | ||
import { C as CD } from "./src/test"; | ||
/*preserve it */ | ||
import { C as CD2, C as CD3 } from "./src/test"; | ||
/*this too */ | ||
import { C as CD4, C as CD5 } from "./src/test"; | ||
/*preserve it */ | ||
export { CD2, CD3 }; | ||
/*this too */ | ||
export { CD4, CD5 }; | ||
/*preserve it */ | ||
export { C as CD6, C as CD7 } from "./src/test"; | ||
/*this too */ | ||
export { C as CD8, C as CD9 } from "./src/test"; | ||
import * as rex_1 from "./src/test"; | ||
@@ -26,0 +38,0 @@ //another comment |
@@ -26,2 +26,14 @@ /// <reference path="./src/test.d.ts" /> | ||
import { C as CD } from "./src/test"; | ||
/*preserve it */ | ||
import { C as CD2, C as CD3 } from "./src/test"; | ||
/*this too */ | ||
import { C as CD4, C as CD5 } from "./src/test"; | ||
/*preserve it */ | ||
export { CD2, CD3 }; | ||
/*this too */ | ||
export { CD4, CD5 }; | ||
/*preserve it */ | ||
export { C as CD6, C as CD7 } from "./src/test"; | ||
/*this too */ | ||
export { C as CD8, C as CD9 } from "./src/test"; | ||
import * as rex_1 from "./src/test"; | ||
@@ -28,0 +40,0 @@ //another comment |
@@ -26,2 +26,14 @@ /// <reference path="./src/test.d.ts" /> | ||
import { C as CD } from "./src/test"; | ||
/*preserve it */ | ||
import { C as CD2, C as CD3 } from "./src/test"; | ||
/*this too */ | ||
import { C as CD4, C as CD5 } from "./src/test"; | ||
/*preserve it */ | ||
export { CD2, CD3 }; | ||
/*this too */ | ||
export { CD4, CD5 }; | ||
/*preserve it */ | ||
export { C as CD6, C as CD7 } from "./src/test"; | ||
/*this too */ | ||
export { C as CD8, C as CD9 } from "./src/test"; | ||
import * as rex_1 from "./src/test"; | ||
@@ -28,0 +40,0 @@ //another comment |
@@ -26,2 +26,17 @@ /// <reference path="./src/test.d.ts" /> | ||
import type { C as CD } from "./src/test"; | ||
/*preserve it */ | ||
import type { C as CD2, C as CD3 } from "./src/test"; | ||
/*this too */ | ||
import type { C as CD5 } from "./src/test"; | ||
import { C as CD4 } from "./src/test"; | ||
/*preserve it */ | ||
export type { CD2, CD3 }; | ||
/*this too */ | ||
export type { CD5 }; | ||
export { CD4 }; | ||
/*preserve it */ | ||
export type { C as CD6, C as CD7 } from "./src/test"; | ||
/*this too */ | ||
export type { C as CD9 } from "./src/test"; | ||
export { C as CD8 } from "./src/test"; | ||
// another comment | ||
@@ -28,0 +43,0 @@ export * as rex from "./src/test"; |
@@ -26,2 +26,17 @@ /// <reference path="./src/test.d.ts" /> | ||
import type { C as CD } from "./src/test"; | ||
/*preserve it */ | ||
import type { C as CD2, C as CD3 } from "./src/test"; | ||
/*this too */ | ||
import type { C as CD5 } from "./src/test"; | ||
import { C as CD4 } from "./src/test"; | ||
/*preserve it */ | ||
export type { CD2, CD3 }; | ||
/*this too */ | ||
export type { CD5 }; | ||
export { CD4 }; | ||
/*preserve it */ | ||
export type { C as CD6, C as CD7 } from "./src/test"; | ||
/*this too */ | ||
export type { C as CD9 } from "./src/test"; | ||
export { C as CD8 } from "./src/test"; | ||
// another comment | ||
@@ -28,0 +43,0 @@ export * as rex from "./src/test"; |
@@ -26,2 +26,17 @@ /// <reference path="./src/test.d.ts" /> | ||
import type { C as CD } from "./src/test"; | ||
/*preserve it */ | ||
import type { C as CD2, C as CD3 } from "./src/test"; | ||
/*this too */ | ||
import type { C as CD5 } from "./src/test"; | ||
import { C as CD4 } from "./src/test"; | ||
/*preserve it */ | ||
export type { CD2, CD3 }; | ||
/*this too */ | ||
export type { CD5 }; | ||
export { CD4 }; | ||
/*preserve it */ | ||
export type { C as CD6, C as CD7 } from "./src/test"; | ||
/*this too */ | ||
export type { C as CD9 } from "./src/test"; | ||
export { C as CD8 } from "./src/test"; | ||
// another comment | ||
@@ -28,0 +43,0 @@ export * as rex from "./src/test"; |
165
index.js
@@ -104,3 +104,2 @@ #!/usr/bin/env node | ||
// set x(value: number) => x: number | ||
let flags = ts.getCombinedModifierFlags(n); | ||
if (getMatchingAccessor(n, "set")) { | ||
@@ -169,3 +168,3 @@ return undefined; | ||
undefined, | ||
ts.createNamedExports([ts.createExportSpecifier(tempName, n.exportClause.name)]) | ||
ts.createNamedExports([ts.createExportSpecifier(false, tempName, n.exportClause.name)]) | ||
) | ||
@@ -178,2 +177,161 @@ ) | ||
return ts.createImportClause(n.name, n.namedBindings); | ||
} else if ( | ||
semver.lt(targetVersion, "4.5.0") && | ||
ts.isImportDeclaration(n) && | ||
!n.modifiers && | ||
n.importClause && | ||
!n.importClause.isTypeOnly && | ||
n.importClause.namedBindings && | ||
ts.isNamedImports(n.importClause.namedBindings) && | ||
n.importClause.namedBindings.elements.some(e => e.isTypeOnly) | ||
) { | ||
const elements = n.importClause.namedBindings.elements; | ||
if (semver.lt(targetVersion, "3.8.0")) { | ||
// import { A, type B } from 'x' | ||
// => | ||
// import { A, B } from 'x' | ||
return copyComment( | ||
[n], | ||
ts.createImportDeclaration( | ||
n.decorators, | ||
n.modifiers, | ||
ts.createImportClause( | ||
n.importClause.name, | ||
ts.createNamedImports(elements.map(e => ts.createImportSpecifier(false, e.propertyName, e.name))) | ||
), | ||
n.moduleSpecifier | ||
) | ||
); | ||
} | ||
const typeElements = []; | ||
const valueElements = []; | ||
for (const e of elements) { | ||
if (e.isTypeOnly) { | ||
typeElements.push(e); | ||
} else { | ||
valueElements.push(e); | ||
} | ||
} | ||
// import { type A, type B, ... } from 'x' | ||
// => | ||
// import type { A, B } from 'x' | ||
const typeOnlyImportDeclaration = copyComment( | ||
[n], | ||
ts.createImportDeclaration( | ||
n.decorators, | ||
n.modifiers, | ||
ts.createImportClause( | ||
n.importClause.name, | ||
ts.createNamedImports(typeElements.map(e => ts.createImportSpecifier(false, e.propertyName, e.name))), | ||
true | ||
), | ||
n.moduleSpecifier | ||
) | ||
); | ||
if (valueElements.length === 0) { | ||
// import { type A, type B } from 'x' | ||
// => | ||
// import type { A, B } from 'x' | ||
return typeOnlyImportDeclaration; | ||
} else { | ||
// import { A, type B } from 'x' | ||
// => | ||
// import type { B } from 'x' | ||
// import { A } from 'x' | ||
return [ | ||
typeOnlyImportDeclaration, | ||
ts.createImportDeclaration( | ||
n.decorators, | ||
n.modifiers, | ||
ts.createImportClause( | ||
n.importClause.name, | ||
ts.createNamedImports(valueElements.map(e => ts.createImportSpecifier(false, e.propertyName, e.name))) | ||
), | ||
n.moduleSpecifier | ||
) | ||
]; | ||
} | ||
} else if ( | ||
semver.lt(targetVersion, "4.5.0") && | ||
ts.isExportDeclaration(n) && | ||
!n.modifiers && | ||
!n.isTypeOnly && | ||
n.exportClause && | ||
ts.isNamedExports(n.exportClause) && | ||
n.exportClause.elements.some(e => e.isTypeOnly) | ||
) { | ||
const elements = n.exportClause.elements; | ||
if (semver.lt(targetVersion, "3.8.0")) { | ||
// export { A, type B } | ||
// export { C, type D } from 'x' | ||
// => | ||
// export { A, B } | ||
// export { C, D } from 'x' | ||
return copyComment( | ||
[n], | ||
ts.createExportDeclaration( | ||
n.decorators, | ||
n.modifiers, | ||
ts.createNamedExports(elements.map(e => ts.createExportSpecifier(false, e.propertyName, e.name))), | ||
n.moduleSpecifier | ||
) | ||
); | ||
} | ||
const typeElements = []; | ||
const valueElements = []; | ||
for (const e of elements) { | ||
if (e.isTypeOnly) { | ||
typeElements.push(e); | ||
} else { | ||
valueElements.push(e); | ||
} | ||
} | ||
// export { type A, type B, ... } | ||
// export { type C, type D, ... } from 'x' | ||
// => | ||
// export type { A, B } | ||
// export type { C, D } from 'x' | ||
const typeOnlyExportDeclaration = copyComment( | ||
[n], | ||
ts.createExportDeclaration( | ||
n.decorators, | ||
n.modifiers, | ||
ts.createNamedExports(typeElements.map(e => ts.createExportSpecifier(false, e.propertyName, e.name))), | ||
n.moduleSpecifier, | ||
true | ||
) | ||
); | ||
if (valueElements.length === 0) { | ||
// export { type A, type B } | ||
// export { type C, type D } from 'x' | ||
// => | ||
// export type { A, B } | ||
// export type { C, D } from 'x' | ||
return typeOnlyExportDeclaration; | ||
} else { | ||
// export { A, type B } | ||
// export { C, type D } from 'x' | ||
// => | ||
// export type { B } | ||
// export { A } | ||
// export type { C } from 'x' | ||
// export { D } from 'x' | ||
return [ | ||
typeOnlyExportDeclaration, | ||
ts.createExportDeclaration( | ||
n.decorators, | ||
n.modifiers, | ||
ts.createNamedExports(valueElements.map(e => ts.createExportSpecifier(false, e.propertyName, e.name))), | ||
n.moduleSpecifier | ||
) | ||
]; | ||
} | ||
} else if (isTypeReference(n, "Omit")) { | ||
@@ -286,3 +444,3 @@ const symbol = checker.getSymbolAtLocation(ts.isTypeReferenceNode(n) ? n.typeName : n.expression); | ||
* @param {string} typeName name of the type | ||
* @returns true if the node is a type reference with typeName as a name | ||
* @returns {node is ts.TypeReferenceNode | ts.ExpressionWithTypeArguments} true if the node is a type reference with typeName as a name | ||
*/ | ||
@@ -306,2 +464,3 @@ function isTypeReference(node, typeName) { | ||
symbol && | ||
symbol.declarations && | ||
symbol.declarations.length && | ||
@@ -308,0 +467,0 @@ symbol.declarations[0].getSourceFile().fileName.includes("node_modules/typescript/lib/lib") |
@@ -7,3 +7,3 @@ const { main } = require("./index"); | ||
describe("main", () => { | ||
const tsVersions = ["3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "4.0"]; | ||
const tsVersions = ["3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "4.0", "4.1", "4.2", "4.3", "4.4", "4.5", "4.6"]; | ||
@@ -10,0 +10,0 @@ if (fs.existsSync(`baselines/local`)) { |
{ | ||
"name": "downlevel-dts", | ||
"version": "0.8.0", | ||
"version": "0.9.0", | ||
"description": "Convert d.ts to be compatible with older typescript compilers", | ||
@@ -19,5 +19,5 @@ "homepage": "https://github.com/sandersn/downlevel-dts", | ||
"dependencies": { | ||
"semver": "^7.3.2", | ||
"shelljs": "^0.8.3", | ||
"semver": "^7.3.2", | ||
"typescript": "^4.1.0-dev.20201026" | ||
"typescript": "^4.5.5" | ||
}, | ||
@@ -24,0 +24,0 @@ "devDependencies": { |
@@ -1,6 +0,6 @@ | ||
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 | ||
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: | ||
TypeScript didn't support accessors in .d.ts files until 3.6: | ||
@@ -22,7 +22,7 @@ ```ts | ||
Note that not all features can be downlevelled. For example, | ||
Typescript 4.0 allows spreading multiple tuple type variables, at any | ||
TypeScript 4.0 allows spreading multiple tuple type variables, at any | ||
position in a tuple. This is not allowed in previous versions, but has | ||
no obvious downlevel emit, so downlevel-dts doesn't attempt to do | ||
anything. Be sure to test the output of downlevel-dts with the | ||
appropriate version of Typescript. | ||
appropriate version of TypeScript. | ||
@@ -45,4 +45,4 @@ ## Features | ||
`Omit` has had non-builtin implementations since Typescript 2.2, but | ||
became built-in in Typescript 3.5. | ||
`Omit` has had non-builtin implementations since TypeScript 2.2, but | ||
became built-in in TypeScript 3.5. | ||
@@ -55,4 +55,4 @@ #### Semantics | ||
Typescript prevented accessors from being in .d.ts files until | ||
Typescript 3.6 because they behave very similarly to properties. | ||
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 | ||
@@ -79,3 +79,3 @@ can be useful. | ||
the original accessors, so the downlevel d.ts will be less strict. See | ||
[the Typescript 3.7 release | ||
[the TypeScript 3.7 release | ||
notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier) | ||
@@ -86,4 +86,4 @@ for more detail. | ||
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. | ||
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. | ||
@@ -143,5 +143,64 @@ Since there is no way to model this before 3.7, such functions are downlevelled to return `void`: | ||
### `type` modifiers on import/export names (4.5) | ||
The downlevel emit depends on the TypeScript target version and whether type and | ||
value imports/exports are mixed. | ||
An import/export declaration with only import/export names that have `type` | ||
modifiers | ||
```ts | ||
import { type A, type B } from "x"; | ||
export { type A, type B }; | ||
``` | ||
becomes: | ||
```ts | ||
// TS 3.8+ | ||
import type { A, B } from "x"; | ||
export type { A, B }; | ||
// TS 3.7 or less | ||
import { A, B } from "x"; | ||
export { A, B }; | ||
``` | ||
A mixed import/export declaration | ||
```ts | ||
import { A, type B } from "x"; | ||
export { A, type B }; | ||
``` | ||
becomes: | ||
```ts | ||
// TS 3.8+ | ||
import type { B } from "x"; | ||
import { A } from "x"; | ||
export type { B }; | ||
export { A }; | ||
// TS 3.7 or less | ||
import { A, B } from "x"; | ||
export { A, B }; | ||
``` | ||
#### Semantics | ||
When an import/export declaration has only import/export names with `type` | ||
modifiers, it is emitted as a type-only import/export declaration for TS 3.8+ | ||
and as a value import/export declaration for TS 3.7 or less. The latter will be | ||
less strict (see [type-only import/export](#type-only-importexport-38)). | ||
When type and value imports/exports are mixed, two import/export declarations | ||
are emitted for TS 3.8+, one for type-only imports/exports and another one for | ||
value imports/exports. For TS 3.7 or less, one value import/export declaration | ||
is emitted which will be less strict (see | ||
[type-only import/export](#type-only-importexport-38)). | ||
### `#private` (3.8) | ||
Typescript 3.8 supports the new ECMAScript-standard #private properties in | ||
TypeScript 3.8 supports the new ECMAScript-standard #private properties in | ||
addition to its compile-time-only private properties. Since neither | ||
@@ -207,3 +266,3 @@ are accessible at compile-time, downlevel-dts converts #private | ||
Typescript 3.8 supports the new ECMAScript-standard `export * as namespace` syntax, which is just syntactic sugar for two import/export | ||
TypeScript 3.8 supports the new ECMAScript-standard `export * as namespace` syntax, which is just syntactic sugar for two import/export | ||
statements: | ||
@@ -228,3 +287,3 @@ | ||
Typescript 4.0 supports naming tuple members: | ||
TypeScript 4.0 supports naming tuple members: | ||
@@ -244,12 +303,12 @@ ```ts | ||
The downlevel semantics are exactly the same as the original, but | ||
the Typescript language service won't be able to show the member names. | ||
the TypeScript language service won't be able to show the member names. | ||
## Target | ||
Since the earliest downlevel feature is from Typescript 3.5, | ||
downlevel-dts targets Typescript 3.4 by default. The downlevel target is | ||
Since the earliest downlevel feature is from TypeScript 3.5, | ||
downlevel-dts targets TypeScript 3.4 by default. The downlevel target is | ||
configurable with `--to` argument. | ||
Currently, Typescript 3.0 features like `unknown` are not | ||
downlevelled, nor are there any other plans to support Typescript 2.x. | ||
Currently, TypeScript 3.0 features like `unknown` are not | ||
downlevelled, nor are there any other plans to support TypeScript 2.x. | ||
@@ -256,0 +315,0 @@ ### Downlevel semantics |
@@ -27,2 +27,14 @@ /// <reference path="./src/test.d.ts" /> | ||
import type { C as CD } from "./src/test"; | ||
/** preserve it */ | ||
import { type C as CD2, type C as CD3 } from "./src/test"; | ||
/** this too */ | ||
import { C as CD4, type C as CD5 } from "./src/test"; | ||
/** preserve it */ | ||
export { type CD2, type CD3 }; | ||
/** this too */ | ||
export { CD4, type CD5 }; | ||
/** preserve it */ | ||
export { type C as CD6, type C as CD7 } from "./src/test"; | ||
/** this too */ | ||
export { C as CD8, type C as CD9 } from "./src/test"; | ||
@@ -29,0 +41,0 @@ // another comment |
61189
65.28%42
40%1825
81.59%323
22.35%Updated