mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Fix crash in JS declaration emit (#38508)
* Fix crash in JS decl emit * Emit as class with private ctor
This commit is contained in:
parent
7fc456f2d7
commit
1cbe7ef000
@ -5949,6 +5949,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Synthesize declarations for a symbol - might be an Interface, a Class, a Namespace, a Type, a Variable (const, let, or var), an Alias
|
||||
// or a merge of some number of those.
|
||||
// An interesting challenge is ensuring that when classes merge with namespaces and interfaces, is keeping
|
||||
@ -6317,7 +6318,10 @@ namespace ts {
|
||||
const baseTypes = getBaseTypes(classType);
|
||||
const implementsTypes = getImplementsTypes(classType);
|
||||
const staticType = getTypeOfSymbol(symbol);
|
||||
const staticBaseType = getBaseConstructorTypeOfClass(staticType as InterfaceType);
|
||||
const isClass = !!staticType.symbol?.valueDeclaration && isClassLike(staticType.symbol.valueDeclaration);
|
||||
const staticBaseType = isClass
|
||||
? getBaseConstructorTypeOfClass(staticType as InterfaceType)
|
||||
: anyType;
|
||||
const heritageClauses = [
|
||||
...!length(baseTypes) ? [] : [createHeritageClause(SyntaxKind.ExtendsKeyword, map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))],
|
||||
...!length(implementsTypes) ? [] : [createHeritageClause(SyntaxKind.ImplementsKeyword, map(implementsTypes, b => serializeBaseType(b, staticBaseType, localName)))]
|
||||
@ -6353,7 +6357,17 @@ namespace ts {
|
||||
const staticMembers = flatMap(
|
||||
filter(getPropertiesOfType(staticType), p => !(p.flags & SymbolFlags.Prototype) && p.escapedName !== "prototype" && !isNamespaceMember(p)),
|
||||
p => serializePropertySymbolForClass(p, /*isStatic*/ true, staticBaseType));
|
||||
const constructors = serializeSignatures(SignatureKind.Construct, staticType, baseTypes[0], SyntaxKind.Constructor) as ConstructorDeclaration[];
|
||||
// When we encounter an `X.prototype.y` assignment in a JS file, we bind `X` as a class regardless as to whether
|
||||
// the value is ever initialized with a class or function-like value. For cases where `X` could never be
|
||||
// created via `new`, we will inject a `private constructor()` declaration to indicate it is not createable.
|
||||
const isNonConstructableClassLikeInJsFile =
|
||||
!isClass &&
|
||||
!!symbol.valueDeclaration &&
|
||||
isInJSFile(symbol.valueDeclaration) &&
|
||||
!some(getSignaturesOfType(staticType, SignatureKind.Construct));
|
||||
const constructors = isNonConstructableClassLikeInJsFile ?
|
||||
[createConstructor(/*decorators*/ undefined, createModifiersFromModifierFlags(ModifierFlags.Private), [], /*body*/ undefined)] :
|
||||
serializeSignatures(SignatureKind.Construct, staticType, baseTypes[0], SyntaxKind.Constructor) as ConstructorDeclaration[];
|
||||
for (const c of constructors) {
|
||||
// A constructor's return type and type parameters are supposed to be controlled by the enclosing class declaration
|
||||
// `signatureToSignatureDeclarationHelper` appends them regardless, so for now we delete them here
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
tests/cases/conformance/jsdoc/declarations/index.js(4,3): error TS2339: Property 'prototype' does not exist on type '{}'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/declarations/index.js (1 errors) ====
|
||||
// https://github.com/microsoft/TypeScript/issues/35801
|
||||
let A;
|
||||
A = {};
|
||||
A.prototype.b = {};
|
||||
~~~~~~~~~
|
||||
!!! error TS2339: Property 'prototype' does not exist on type '{}'.
|
||||
@ -0,0 +1,18 @@
|
||||
//// [index.js]
|
||||
// https://github.com/microsoft/TypeScript/issues/35801
|
||||
let A;
|
||||
A = {};
|
||||
A.prototype.b = {};
|
||||
|
||||
//// [index.js]
|
||||
// https://github.com/microsoft/TypeScript/issues/35801
|
||||
var A;
|
||||
A = {};
|
||||
A.prototype.b = {};
|
||||
|
||||
|
||||
//// [index.d.ts]
|
||||
declare class A {
|
||||
private constructor();
|
||||
b: {};
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
=== tests/cases/conformance/jsdoc/declarations/index.js ===
|
||||
// https://github.com/microsoft/TypeScript/issues/35801
|
||||
let A;
|
||||
>A : Symbol(A, Decl(index.js, 1, 3))
|
||||
|
||||
A = {};
|
||||
>A : Symbol(A, Decl(index.js, 1, 3))
|
||||
|
||||
A.prototype.b = {};
|
||||
>A.prototype : Symbol(A.b, Decl(index.js, 2, 7))
|
||||
>A : Symbol(A, Decl(index.js, 1, 3))
|
||||
>b : Symbol(A.b, Decl(index.js, 2, 7))
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
=== tests/cases/conformance/jsdoc/declarations/index.js ===
|
||||
// https://github.com/microsoft/TypeScript/issues/35801
|
||||
let A;
|
||||
>A : any
|
||||
|
||||
A = {};
|
||||
>A = {} : {}
|
||||
>A : any
|
||||
>{} : {}
|
||||
|
||||
A.prototype.b = {};
|
||||
>A.prototype.b = {} : {}
|
||||
>A.prototype.b : any
|
||||
>A.prototype : any
|
||||
>A : {}
|
||||
>prototype : any
|
||||
>b : any
|
||||
>{} : {}
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @target: es5
|
||||
// @outDir: ./out
|
||||
// @declaration: true
|
||||
// @filename: index.js
|
||||
// https://github.com/microsoft/TypeScript/issues/35801
|
||||
let A;
|
||||
A = {};
|
||||
A.prototype.b = {};
|
||||
Loading…
x
Reference in New Issue
Block a user