-
-
Notifications
You must be signed in to change notification settings - Fork 735
Use npm @types/*
for 3rd party type definitions
#310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Use the latest `typescript.d.ts` definitions - Add `ts-internal.ts` to expose the internal Typescript APIs (that TypeDoc is currently using) using declaration merging - Remove tsd and typings files Closes TypeStrong#309
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like all these changes, especially pulling out the internal TS apis that are used. Glad to see people helping move this forward 👍
declare module "shelljs" { | ||
// `stdout` was added in: | ||
// https://github.com/shelljs/shelljs/commit/8a7f7ceec4d3a77a9309d935755675ac368b1eda#diff-c3bfabb5e6987aa21bc75ffd95a162d6 | ||
// As of 2016-10-16, DefinitelyTyped's defs are for shelljs v0.3.0, but we're on 0.7.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Has anyone created a PR to update this yet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not find any updates or PRs for shelljs
|
||
/** | ||
* Expose the internal TypeScript APIs that are used by TypeDoc | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to identifying the internal APIs so we can move off of them. Way to also link to the internal TS definitions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any concern about the out-datedness that could occur here? Is there a way to build it with the internal APIs exposed instead and use that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any concern about the out-datedness that could occur
That is certainly a concern. My hope is that these internal usages can be replaced by other APIs.
@@ -4,6 +4,20 @@ import {Type, IntrinsicType} from "../../models/index"; | |||
import {Component, ConverterTypeComponent, ITypeTypeConverter} from "../components"; | |||
import {Context} from "../context"; | |||
|
|||
// Copy typescript's @internal enum set from: | |||
// https://github.com/Microsoft/TypeScript/blob/v2.0.5/src/compiler/types.ts#L2297-L2298 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason you defined this here instead of ts-internal.ts
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code in ts-internal.ts
exposes the existing internal/hidden APIs by augmenting the "typescript" module and exported interfaces.
In this case, the TypeFlags
enum itself is exported from ts
namespace. However, the Intrinsic
enum value is marked as @hidden
. I could not find a way to augment the existing TypeFlags
enum (which is exposed as a public API) with a new enum value (which is @internal and hidden). Since I couldn't cleanly expose something from the typescript
module using an augmentation, I decided to move it outside that file.
The other option, I suppose, is to export it from the ts-internal.ts
file as a separate symbol (not inside the typescript
namespace). I don't really have a strong opinion on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. Unless it is needed in multiple places, defining it here is good with me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about using any
to access this? My only fear is forgetting to update it if anything changes in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm ok with the any
approach.
@@ -13,32 +13,19 @@ | |||
"experimentalDecorators": true | |||
}, | |||
"exclude": [ | |||
"./node_modules/typescript/lib/typescript.d.ts", | |||
"./typescript/lib/typescript.d.ts" | |||
], | |||
"filesGlob": [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should files
/filesGlob
be migrated to include
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure. What do you think? I didn't change it for fear of "not knowing what I don't know".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I honestly haven't used include
yet but I think filesGlob
is only supported via plugins so it would make sense to me to move to the official property with glob support. I'm curious what others think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kill filesGlob
, nothing uses it anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will kill filesGlob
and the now empty exclude
Thanks a ton! It's really awesome. My only concern is with the possible out-datedness that can occur when we pull the TypeScript definition in manually, but it's an amazing start. Thanks for the PR 😄 |
@christopherthielen Did you only bring in the definitions that were used? It'd be great to try to reduce this list with future PRs (anyone interested 😉). |
@aciccarello yes, the only internal APIs I added typings for are the APIs that TypeDoc is currently using. |
When I created this PR, I thought the I did a little experimenting and found out that it's trivial to generate the full
I'll see if I can automate the generation of a subset of that file, including only the internal apis being used. Potentially we could just use the full |
Understandable. FWIW, I think |
It's generated as you have described. There is an |
@DatenMetzgerX oh, that's great to know and understand, thanks! I completely missed those instructions. I guess the question related to this PR is then: which would ya'll prefer:
Option 1 is the easiest, and is what the project currently uses. We could move to Option 2 could be automated and might be a step towards a goal of eliminating (or reducing) use of internal APIs altogether. I have this process partially automated. I suppose I'll finish automating it and add it to the PR, then ya'll can take a look and make a decision. |
The only question I have: will this cause "duplicate identifier" errors, if you have some of the typings already installed? |
@felixfbecker this is only for building typedoc, so it shouldn't affect your project's doc generation. |
@christopherthielen I don't think so, when using typings programmatically in TypeScript it will depend on the typings. |
@felixfbecker That's a real PITA. I remember having this conversation with the TypeScript team before because we can fix this on our end by providing a custom |
@felixfbecker @blakeembrey I'm not sure I understand what the problem is. Can one of you clarify? Is the problem related to using Is it about using the internal TypeScript APIs? Or about exposing those internal APIs in |
@christopherthielen Shouldn't affect the existing discussion, but in case you're interested it's related to #281. Basically, we should move to a system where we can publish the typings included so people can use it programmatically. However, if we For now, don't worry about it, it's just a related conversation that was somewhat relevant and it's a good example for a point I logged a while back in May (?) for TS 2.0 module support. Edit: Note that this is only a solid issue if we expose any transitive types. We might not even do that, which makes the issue semi-mute as the workaround is just avoid it. However, it's still something that may occur unexpectedly in the future if we ever accidentally re-expose a type. A bigger issue too is that the definition we re-expose could end up different to the one we actually use (if it's compiled separately) which would be bad because the module we publish can't even be used with TypeScript. |
@blakeembrey based on this information, I think we should do the following:
Instead of adding them back into the "typescript" module (like import { getJsDocComments } from "../ts-internal";
For example, this works: declare module "typescript" {
interface Symbol {
id?: number;
parent?: ts.Symbol;
}
}
declare module "typescript" {
interface Symbol {
parent?: ts.Symbol;
}
}
export interface CommandLineOption {
name: string;
type: string;
shortName: string;
description: DiagnosticsEnumValue;
paramType: DiagnosticsEnumValue;
} Of course, we'll have to maintain them ourselves, but it seems like this approach would address both issues. |
For what it's worth, I'm also affected by #281. My kludge currently looks like so: https://github.com/christopherthielen/typedoc-plugin-internal-external/blob/master/tsconfig.json#L12 |
@christopherthielen What about the handlebars typings dependency? Currently it gives a "cannot find module..." when using typedoc programmatically. I assume with this PR that will go away, but what if I already have typings for handlebars installed in my project, e.g. some file that does |
@felixfbecker because the typings in this PR are listed as |
@christopherthielen That's a good point. Given that, can we make them dependencies? It'll be much more valuable if someone can actually use this module from NPM without having to manually install the dependent types. |
I would say the core here is not custom typeRoots, but the use of private APIs. These APIs are marked private as there are no support promises here. so they could be broken at will or removed all together. As for typeRoots; this is mainly for users who want to override declarations of a certain package, but I do not think it should be used to publish a dependency. republishing declarations of other packages in general have proved painful for everybody. so my recommendation is to get the original package author to include them (in this case Typescript :)), or have a new package that "expands" on the original package, e.g. publish I left a few comments on the PR. Feel free to ignore them, i just found it easier to leave them on the code rather than listing them all on one comment. |
|
||
interface Node { | ||
// https://github.com/Microsoft/TypeScript/blob/v2.0.5/src/compiler/types.ts#L469 | ||
symbol?: ts.Symbol; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use TypeChecker.getSymbolAtLocation
instead.
// https://github.com/Microsoft/TypeScript/blob/v2.0.5/src/compiler/types.ts#L469 | ||
symbol?: ts.Symbol; | ||
// https://github.com/Microsoft/TypeScript/blob/v2.0.5/src/compiler/types.ts#L472 | ||
localSymbol?: ts.Symbol; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not think you should ever use this. it is misleading, and very subtle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I used this to get the local name of a default export
// https://github.com/Microsoft/TypeScript/blob/v2.0.5/src/compiler/types.ts#L2166 | ||
id?: number; | ||
// https://github.com/Microsoft/TypeScript/blob/v2.0.5/src/compiler/types.ts#L2168 | ||
parent?: ts.Symbol; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can expose this. please file an issue for it.
declare module "typescript" { | ||
interface Symbol { | ||
// https://github.com/Microsoft/TypeScript/blob/v2.0.5/src/compiler/types.ts#L2166 | ||
id?: number; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can expose a getter on the Symbol class to expose this as needed. please file an issue for it.
// https://github.com/Microsoft/TypeScript/blob/v2.0.5/src/compiler/types.ts#L472 | ||
localSymbol?: ts.Symbol; | ||
// https://github.com/Microsoft/TypeScript/blob/v2.0.5/src/compiler/types.ts#L471 | ||
nextContainer?: ts.Node; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not use this. there are better ways to accomplish what you want.
* | ||
* Faking the enum as a var (only certain codes are used by TypeDoc) | ||
*/ | ||
var CharacterCodes: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can expose this. though it is just ASCII codes, so you can define them yourself rely.
* Duplicating the interface definition :( | ||
*/ | ||
interface IntrinsicType extends ts.Type { | ||
intrinsicName: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use TypeChecker.typeToString(type)
instead.
intrinsicName: string; | ||
} | ||
|
||
const optionDeclarations: CommandLineOption[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure why this is needed. but if you have a good use case we can expose it.
function getTextOfNode(node: ts.Node, includeTrivia?: boolean): string; | ||
|
||
// https://github.com/Microsoft/TypeScript/blob/v2.0.5/src/compiler/utilities.ts#L438 | ||
function declarationNameToString(name: ts.DeclarationName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use TypeChecker.symbolToString
instead.
function getClassExtendsHeritageClauseElement(node: ts.ClassLikeDeclaration | ts.InterfaceDeclaration); | ||
|
||
// https://github.com/Microsoft/TypeScript/blob/v2.0.5/src/compiler/utilities.ts#L1701 | ||
function getClassImplementsHeritageClauseElements(node: ts.ClassLikeDeclaration); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nor this.
@mhegazy What do you think about the fact that this module depends on some packages that do not have included typings, like handlebars? The idea is to make |
@mhegazy thanks for the feedback on the internal API usage! |
I'll make another attempt at this PR in the next few days taking into account all this new information. |
Let's say typedoc has a dependency with The issue here is really how "compilerOptions": {
"typeRoots": [ "./typings", "./node_modules/@types" ]
} this way the compiler will look at But the main problem here is https://github.com/DefinitelyTyped/DefinitelyTyped/blob/types-2.0/handlebars/index.d.ts, it should be authored as: ...
export = Handlebars; instead of: ...
declare module "handlebars" {
export = Handlebars;
} |
"@types/lodash": "^4.14.37", | ||
"@types/marked": "0.0.28", | ||
"@types/minimatch": "^2.0.29", | ||
"@types/shelljs": "^0.3.32", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we can move all these to dependencies
, I'd be happy to merge today and leave the rest of the awesome comments from @mhegazy for a future PR. I'll open an issue for them too, once this PR lands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
I'm not 100% sure this is the right thing to do though. I think we only need to add as dependencies
those @types/* packages which are exposed via a public API in the typedoc.d.ts files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@christopherthielen No, user's code won't compile if not all modules referenced in the declaration files are available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@felixfbecker I guess that's my point, though. Only those typings that are referenced in the declaration files need to be in dependencies
.
Edit: in fact, only @types/handlebars
is referenced in the typedoc declaration files:
╰─ git:[masterUNSTAGED] grep -R "///" .
./output/events.d.ts:/// <reference types="handlebars" />
./output/utils/resources/templates.d.ts:/// <reference types="handlebars" />
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's understandable. The issue with it is that you might accidentally expose one or the other at some point and forget to move them around. I think putting them in the same place as the real dependency is the best approach to avoid unfortunate side-effects.
@mhegazy Thanks for all your comments.
I agree, I was trying to allude to the larger problem as it was part of a discussion we'd had in the past. As a module author, if there's an incorrect definition, I'd like to override |
This PR removes the typings files from
typedoc/src/typings
in favor of using npm@types/*
packages.It now (automatically) uses the official
typescript.d.ts
definitions fromnode_modules/typescript/lib/typescript.d.ts
.TypeDoc uses quite a few internal TypeScript APIs. Those APIs were exposed in the (old?)
typescript.d.ts
from DefinitelyTyped.To accommodate TypeDoc's existing use of internal TypeScript APIs, I created a
ts-internal.ts
file. The file augments the official type definitions with the internal APIs that we are using.Obviously it would be best not to use the internal APIs at all. This first pass can be used to identify which internal APIs we are using, so we can work towards replacing those uses with official API.