sandersn / downlevel-dts Goto Github PK
View Code? Open in Web Editor NEWConvert a new d.ts to one that works with older versions of Typescript
License: MIT License
Convert a new d.ts to one that works with older versions of Typescript
License: MIT License
declare abstract class DefinitionBase<TType extends string> {}
declare abstract class DefinitionBase<TType extends string> {}
declare abstract class DefinitionBase< extends string> {}
We run downlevel-dts as instructed here, with: downlevel-dts . ts3.4 && cp tsconfig.json ./ts3.4/
, but on subsequent runs this causes the ./ts3.4 folder to be read as input and then included in the output folder.
We get something like
.
├── lib
├── ...
├── ts3.4
│ ├── ...
│ ├── ts3.4
│ │ ├── ...
│ │ ├── ts3.4
Seems like downlevel-dts should exclude the output folder from its inputs.
➤ YN0000: DeprecationWarning: 'createExportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createExportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createImportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createPropertyDeclaration' has been deprecated since v4.8.0. Decorators have been combined with modifiers. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createExportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createExportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createImportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createPropertyDeclaration' has been deprecated since v4.8.0. Decorators have been combined with modifiers. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createExportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createExportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createImportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createExportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createImportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createExportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createExportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createExportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createImportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createImportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createNamedImports' has been deprecated since v4.0.0. Use the appropriate method on 'ts.factory' or the 'factory' supplied by your transformation context instead.
➤ YN0000: DeprecationWarning: 'createImportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createImportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
➤ YN0000: DeprecationWarning: 'createExportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
Reference: https://github.com/microsoft/TypeScript/wiki/API-Breaking-Changes
I have a project that puts typings into a folder like:
\typings\latest\src\foo.d.ts
\typings\latest\test\bar.d.ts
I try running downlevel-dts against this folder like so npx downlevel-dts typings\latest typings\3.4
I end up with a typings\3.4
folder, but besides having src
and test
, it also has a path that looks like the path in my monorepo down to where my package.json is (with some of the beginning chopped off):
typings\3.4\dk-for-js\sdk\storage\storage\blob\typings\latest\...
Error: Debug Failure. Unhandled SyntaxKind: ImportClause.
Error: Debug Failure. Unhandled SyntaxKind: NamedExports.
Or at least running on multiple directories.
I've added this module to jest (super grateful it exists!), but I have to call downlevel-dts
in all the directories in the monorepo (I currently loop through all directories and spawn inside each). It'd be awesome if I could pass a list of all the projects I want to build in addition to the paths
- import type {Something} from 'somewhere';
# import {Something} from 'somewhere';
TS 4.1 adds support for export * as default from 'foo'
. This should downlevel to two statements:
import * as _x from 'foo'
export default _x
Hey Nathan,
Thanks for the tweet and this is an excellent use case for the library!
I noticed a few things that might improve this:
GetAccessorDeclaration#getSetAccessor()
helper method. This will help you get the set accessor for a get accessor. A similar method exists on SetAccessorDeclaration
. I actually went to look at these methods just a little while ago though and there were a few bugs in them (one of the first methods I wrote in the library). Upgrade to ts-morph 4.3.1 and those issues are fixed (it didn't work outside class declarations and didn't check if isStatic()
was equal for both of the nodes). I just did a release right now.f.copy(...)
will return the copied source file, so you could copy first then modify that source file. That will save an additional trip to the file system.TODO: Just thought of this, but replaceWithText
will also replace the js docs so we need to also include those here.
Also, perhaps I should add a toProperty()
method in ts-morph that would change get and set accessors to either property declarations or property assignments depending on the parent.
With typescript 4 we want to make 3 versions of our builds, normal dist with latest (4+) and allso 3.4 and 3.8 versions like:
"typesVersions": {
"<3.8": {
"*": [
"ts3.4/*"
]
},
">=3.8 <4.0": {
"*": [
"ts3.8/*"
]
}
},
And the build script:
"build": "tsc && downlevel-dts . ts3.4 --to=3.4 && cp tsconfig.json ./ts3.4/ && downlevel-dts . ts3.8 --to=3.8 && cp tsconfig.json ./ts3.8/ && rm -rf ./ts3.8/ts3.4",
Note: I have to remove files from ts3.4 in previous step ending up in ts3.8
If you see anything I did wrong with this I whould love to know. Else it whould be great with an optional argument that excempts files that we do not want to end up in the target.
3.7 d.ts:
/**
* Gets the lease Id.
*
* @readonly
* @memberof BlobLeaseClient
* @type {string}
*/
get leaseId(): string;
Generated downlevel d.ts:
readonly leaseId: string;
Would be nice to preserve these comments for IntelliSense
export const foo: (_: number | string) => asserts _ is number = (_) => {};
export declare const foo: (_: number | string) => asserts _ is number;
export function foo(_: number | string): asserts _ is number {}
node | 12.18.2 |
downlevel-dts | 0.6.0 |
command | node_modules/.bin/downlevel-dts dist/my-package dist/my-package/ts3.4 --to=3.4 |
I'm working on an RFC for how we manage Ember's ecosystem-wide SemVer commitments and TS together (🎉) and one of the elements I'm designing in the midst of it is the use of downlevel-dts
to handle breaking changes across minor versions of TS. The current approach of supporting 3.4+ is good enough to get the job done (and in my testing so far, I really appreciate downlevel-dts
's level of "it just works"!)—but what we'd really like to be able to do is generate a .d.ts
file for each TS version in a given package's support matrix, so that given a set of source files, you'd do something like this:
yarn downlevel-dts --to=3.6 . ts3.6
yarn downlevel-dts --to=3.7 . ts3.7
yarn downlevel-dts --to=3.8 . ts3.8
Deciding automatically which need to be built, a la #26, would also be super neat, but having this level of granularity for us would be really helpful. In particular, we'd prefer that making a change to support a new version of TS doesn't entail changing the types published for users who haven't upgraded TS yet.
For example: we'd really prefer that when 3.8 added support for type-only imports and exports, our emit for 3.7 consumers didn't revert from get
semantics to readonly
semantics.
If there's interest, I'm very happy to do the implementation work. Having read the source, it looks to be neither trivial nor extremely difficult, and it would be extremely valuable for our use case!
Repro (bash):
echo 'export type A = [one: 1, two: [three: 3, four: 4]]' > test.d.ts
npx [email protected] test.d.ts out.d.ts
cat out.d.ts
Result:
export type A = [
/*one*/ 1,
/*two*/ [
three: 3,
four: 4
]
];
Expected:
export type A = [
/*one*/ 1,
/*two*/ [
/*three*/ 3,
/*four*/ 4
]
];
This can be worked around by running downlevel-dts
multiple times, but it's hard to know how many!
import { RawSourceMap } from 'source-map';
interface FixedRawSourceMap extends Omit<RawSourceMap, 'version'> {
version: number;
}
Output:
import { RawSourceMap } from 'source-map';
interface FixedRawSourceMap extends Omit<RawSourceMap, 'version'> {
version: number;
}
Using 0.4.0
Workaround:
import { RawSourceMap } from 'source-map';
type SourceMapWithVersion = Omit<RawSourceMap, 'version'>;
interface FixedRawSourceMap extends SourceMapWithVersion {
version: number;
}
IteratorResult<T, T>
For TS version < 3.6, IteratorResult
takes only one argument -> IteratorResult<T>
.
For TS version >= 3.6, IteratorResult
takes two arguments -> IteratorResult<T, TReturn = any>
(the second one is optional).
TSC compilation would fail for TS version<3.6 when used IteratorResult<T, T>
.
IteratorResult
in version 3.9interface IteratorYieldResult<TYield> {
done?: false;
value: TYield;
}
interface IteratorReturnResult<TReturn> {
done: true;
value: TReturn;
}
type IteratorResult<T, TReturn = any> = IteratorYieldResult<T> | IteratorReturnResult<TReturn>;
IteratorResult
in version 3.3interface IteratorResult<T> {
done: boolean;
value: T;
}
It seems appropriate to downlevel IteratorResult<T, T>
(or even IteratorResult<T, TReturn>) to IteratorResult<T>
.
export * as TSESTree from './ts-estree';
import * as TSESTree from './ts-estree';
export { TSESTree };
import * as TSESTree_1 from './ts-estree';
export { TSESTree_1 as TSESTree } from './ts-estree';
See also
Test input:
Lines 27 to 28 in ca924f6
Incorrect test output:
downlevel-dts/baselines/ts3.4/test.d.ts
Lines 24 to 26 in ca924f6
I recently came across an issue with this package where JSDoc comments in getters would get incorrectly downleveled and become regular multi-line comments, which lose all the properties of a JSDoc comment. Here's an example of that taken from the bson package
declare class ObjectId {
/**
* The generation time of this ObjectId instance
* @deprecated Please use getTimestamp / createFromTime which returns an int32 epoch
*/
get generationTime(): number;
set generationTime(value: number);
}
becomes
declare class ObjectId {
/*
* The generation time of this ObjectId instance
* @deprecated Please use getTimestamp / createFromTime which returns an int32 epoch
*/
generationTime: number;
}
One big difference in the downlevel output is there aren't any map files.
Maybe it's too out of scope, since the original offsets would no longer line up?
as const
released in 3.4 makes dealing with constant strings and numbers much easier for library authors. Unfortunately, we have not been able to adopt it and also support typescript <3.4 users. It would be great if this could support down leveling as const
.
Currently, I end up doing something like this . Enums are ok for internal usage, but const objects with as const
are my preference for publicly exported values. It allows users to easily supply literal values where we expect a union of possible values.
Node 18.7.0
TypeScript 4.8.2
Worked in downlevel-dts
v 0.10.0; broken in 0.10.1
/home/ntucker/src/rest-hooks/node_modules/downlevel-dts/node_modules/typescript/lib/typescript.js:28803
➤ YN0000: return node.kind === 162 /* ComputedPropertyName */;
➤ YN0000: ^
➤ YN0000:
➤ YN0000: TypeError: Cannot read properties of undefined (reading 'kind')
➤ YN0000: at Object.isComputedPropertyName (/home/ntucker/src/rest-hooks/node_modules/downlevel-dts/node_modules/typescript/lib/typescript.js:28803:21)
➤ YN0000: at Object.createPropertyDeclaration (/home/ntucker/src/rest-hooks/node_modules/downlevel-dts/node_modules/typescript/lib/typescript.js:23287:20)
➤ YN0000: at transform (/home/ntucker/src/rest-hooks/node_modules/downlevel-dts/index.js:96:20)
➤ YN0000: at visitNodes (/home/ntucker/src/rest-hooks/node_modules/downlevel-dts/node_modules/typescript/lib/typescript.js:89111:48)
➤ YN0000: at Object.visitEachChild (/home/ntucker/src/rest-hooks/node_modules/downlevel-dts/node_modules/typescript/lib/typescript.js:89579:362)
➤ YN0000: at transform (/home/ntucker/src/rest-hooks/node_modules/downlevel-dts/index.js:374:15)
➤ YN0000: at visitNodes (/home/ntucker/src/rest-hooks/node_modules/downlevel-dts/node_modules/typescript/lib/typescript.js:89111:48)
➤ YN0000: at visitLexicalEnvironment (/home/ntucker/src/rest-hooks/node_modules/downlevel-dts/node_modules/typescript/lib/typescript.js:89151:22)
➤ YN0000: at Object.visitEachChild (/home/ntucker/src/rest-hooks/node_modules/downlevel-dts/node_modules/typescript/lib/typescript.js:89702:55)
➤ YN0000: at transform (/home/ntucker/src/rest-hooks/node_modules/downlevel-dts/index.js:374:15)
Something like npx downlevel-dts . ts3.4
doesn't work at the moment, because the version of the package that is published on NPM doesn't have "bin": "index.js",
in its package.json.
Instead you get an error: command not found: downlevel-dts
there is missing support for template literal types introduced in TS 4.1
export declare type Greeting = `hello ${World}`
declare type World = 'world'
↓↓↓ downlevel-dts
↓↓↓
export declare type Greeting = `hello ${World}`
declare type World = 'world'
export declare type Greeting = `hello ${World}`
declare type World = 'world'
↓↓↓ downlevel-dts
↓↓↓
// Good enough
export declare type Greeting = string
// This would be awesome
export declare type Greeting = `hello world`
declare type World = 'world'
This is a spin-off of the discussion started in #23. Theoretically it would be possible for this tool to modify the typesVersions
entry of a package.json file automatically depending on the features used.
If for example no feature is used which requires any down-leveling no typesVersions
property could be created at all.
If for example a private field is used in the codebase downlevel-dts could create a folder with the down-leveled files and at the same time it could update the typesVersions
entry to point to that folder.
If for example a private field and accessors are used in the same codebase downlevel-dts could create two folders with the down-leveled files for TypeScript below 3.8 and for TypeScript below 3.7. It could also update the typesVersions
entry to point to those two folders.
Typescript 4.5 has introduced the Awaited type, which recursively extracts the value inside a promise.
I wanted to contribute to this library, but I got confused about how to implement it since it calls itself:
type Awaited<T> =
T extends null | undefined ? T : // special case for `null | undefined` when not in `--strictNullChecks` mode
T extends object & { then(onfulfilled: infer F): any } ? // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped
F extends ((value: infer V, ...args: any) => any) ? // if the argument to `then` is callable, extracts the first argument
Awaited<V> : // recursively unwrap the value
never : // the argument to `then` was not callable
T; // non-object or non-thenable
I was able to downlevel it from:
export type K<T> = Awaited<Promise<T>>;
to
export type K<T> = T extends null | undefined ? T : T extends object & {
then(onfulfilled: infer F): any;
} ? F extends ((value: infer V, ...args: any) => any) ? Awaited<V> : never : T;
As you can see, Awaited calls itself recursively. I tried to look for different similar types that call themselves recursively, but I found none.
I'll be happy to create a PR for this, but I'm not sure how to proceed from here.
You can see here my current attempt.
It would be very cool if this project would support stripping down variance annotations that were introduced recently in microsoft/TypeScript#48240
Is there any reason for it? Currently it means locally, every CI build, every single build of anyone using the AWS CDK we pull down a Typescript nightly. This is a huge amount of energy, bandwidth, etc etc that is just burned because of a config issue or error.
What TS should this be targeting or is it deliberately TS next despite not supporting Typescript 5?
export declare class C {
#private: string;
}
Proposed emit
declare const private: unique symbol;
export declare class C {
private [private]: string
}
TS 4.5 added type
modifiers on import names which is a great syntax improvement IMO. To adopt this feature more quickly in a library, declaration files need to be downleveled to a compatible syntax:
type
modifiersIf an input d.ts has a reference directive like
/// <reference types="node" />
then that line will appear twice in the output d.ts:
/// <reference types="node" />
/// <reference types="node" />
Original d.ts
export { WebResource }
Generated d.ts
export { WebResource };
This is pretty minor, not sure that it hurts anything, but noticed it when looking at diffs.
[email protected] introduce new readonly array & readonly tuple syntax. It generates keyword 'readonly' that's not supported before 3.4. So why not downlevel it to make .d.ts compatible with 3.0~3.4.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.