microsoft / microsoft/TypeScript
declarations file of extended class type is needlessly verbose (excessively deep)
@weswigham がすでに取り組んでいます。
2023年6月21日 から。
- 主要言語
- Go
- スター
- 111k
- フォーク
- 14.4k
- 平均マージ
- 1日 19時間
- マージ済み PR(30日)
- 117
説明
Bug Report
When returning an extended class type from a function, the resulting .d.ts file is needlessly verbose resulting in very, very long .d.ts for chained extensions. (See playground for details).
🔎 Search Terms
emitDeclarations
polymorphic this
mixins
Base constructor must have same return type
Type instantiation is excessively deep and possibly infinite
🕗 Version & Regression Information
- Version v4.2.3 is the minimum version where the code can run without errors.
- All versions output this repeated structure
⏯ Playground Link
💻 Code
class CustomElement extends HTMLElement {
/**
* Useless constructor needed to workaround TS
* `Base constructors must all have the same return type.`
*/
constructor(...args: any) {
super();
}
/* Extends Class.prototype and returns new Class */
static define<
CLASS extends typeof CustomElement,
ARGS extends ConstructorParameters<CLASS>,
INSTANCE extends InstanceType<CLASS>,
PROPS extends object>
(this: CLASS, source: PROPS & ThisType<PROPS & INSTANCE>)
: CLASS & (new (...args: ARGS) => INSTANCE & PROPS) {
return Object.defineProperties(
this.prototype,
source as any,
) as any;
}
}
/** FooElement.js */
class FooElement extends CustomElement
.define({
/** Comment hover test */
definedInFoo1: true,
})
.define({
definedInFoo2: 'bar',
})
.define({
definedInFoo3: 3,
})
.define({
/** Sets 2 to 'foo' */
fooMethod() {
this.definedInFoo2 = 'foo';
}
}) { }
🙁 Actual behavior
Here's the outputed d.ts:
declare class CustomElement extends HTMLElement {
/**
* Useless constructor needed to workaround TS
* `Base constructors must all have the same return type.`
*/
constructor(...args: any);
static define<CLASS extends typeof CustomElement, ARGS extends ConstructorParameters<CLASS>, INSTANCE extends InstanceType<CLASS>, PROPS extends object>(this: CLASS, source: PROPS & ThisType<PROPS & INSTANCE>): CLASS & (new (...args: ARGS) => INSTANCE & PROPS);
}
declare const FooElement_base: typeof CustomElement & (new (...args: any) => CustomElement & {
/** Comment hover test */
definedInFoo1: boolean;
}) & (new (...args: any) => CustomElement & {
/** Comment hover test */
definedInFoo1: boolean;
} & {
definedInFoo2: string;
}) & (new (...args: any) => CustomElement & {
/** Comment hover test */
definedInFoo1: boolean;
} & {
definedInFoo2: string;
} & {
definedInFoo3: number;
}) & (new (...args: any) => CustomElement & {
/** Comment hover test */
definedInFoo1: boolean;
} & {
definedInFoo2: string;
} & {
definedInFoo3: number;
} & {
/** Sets 2 to 'foo' */
fooMethod(): void;
});
/** FooElement.js */
declare class FooElement extends FooElement_base {
}
🙂 Expected behavior
I expected FooElement_base to be shorter, smaller d.ts like this:
declare const FooElement_base: typeof CustomElement & (new (...args: any) => CustomElement & {
/** Comment hover test */
definedInFoo1: boolean;
definedInFoo2: string;
definedInFoo3: number;
/** Sets 2 to 'foo' */
fooMethod(): void;
});
It seems repeated structures aren't analyzed and flattened. I also don't see a way to flatten them myself. Changing CLASS to {[P in keyof CLASS]: CLASS[P]} will make each item reiterate every single property in HTMLElement in the d.ts.
This is a short reproducible, but actual code can get really heavy especially with mixins. I believe (but can't confirm), it causes the "Type instantiation is excessively deep and possibly infinite" error as well. There's probably a performance gain somewhere here as well. I know TS will flatten types, but not constructor return arguments. Maybe, simplified that's the core issue.
I have a second playground link that has a more verbose example including mixin patterns and extending classes extending classes:
Related:
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
評価
この issue はまだ評価されていません。