Add support for declaration merging with different type parameter arity

This commit is contained in:
Zzzen 2023-07-23 18:02:58 +08:00
Родитель 01b18215ec
Коммит c01da59da0
5 изменённых файлов: 302 добавлений и 5 удалений

Просмотреть файл

@ -18783,16 +18783,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// parameters that are in scope (and therefore potentially referenced). For type literals that
// aren't the right hand side of a generic type alias declaration we optimize by reducing the
// set of type parameters to those that are possibly referenced in the literal.
let outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true);
const allDeclarations = type.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) ? [declaration] : type.symbol.declarations!;
let outerTypeParameters = [...flatMap(allDeclarations, declaration => getOuterTypeParameters(declaration, /*includeThisTypes*/ true))];
if (isJSConstructor(declaration)) {
const templateTagParameters = getTypeParametersFromDeclaration(declaration as DeclarationWithTypeParameters);
outerTypeParameters = addRange(outerTypeParameters, templateTagParameters);
}
typeParameters = outerTypeParameters || emptyArray;
const allDeclarations = type.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) ? [declaration] : type.symbol.declarations!;
typeParameters = (target.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) || target.symbol.flags & SymbolFlags.Method || target.symbol.flags & SymbolFlags.TypeLiteral) && !target.aliasTypeArguments ?
filter(typeParameters, tp => some(allDeclarations, d => isTypeParameterPossiblyReferenced(tp, d))) :
typeParameters;
filter(outerTypeParameters, tp => some(allDeclarations, d => isTypeParameterPossiblyReferenced(tp, d))) :
outerTypeParameters;
links.outerTypeParameters = typeParameters;
}
if (typeParameters.length) {

Просмотреть файл

@ -0,0 +1,42 @@
//// [tests/cases/conformance/interfaces/declarationMerging/mergeTwoInterfaces3.ts] ////
//// [mergeTwoInterfaces3.ts]
interface Chainable<Subject = any> {
within(fn: (prevSubject: Subject) => Chainable<Subject>): Chainable<Subject>;
}
interface Chainable<Subject = any, ExtraType = undefined> {
within(fn: (prevSubject: Subject, extra: ExtraType) => Chainable<Subject>): Chainable<Subject, ExtraType>;
}
interface ChainableLike<Subject = any, ExtraType = undefined> {
within(fn: (prevSubject: Subject) => Chainable<Subject>): Chainable<Subject>;
within(fn: (prevSubject: Subject, extra: ExtraType) => Chainable<Subject>): Chainable<Subject, ExtraType>;
}
type ChainableWithSecondType = Chainable<string, string>;
type Merged = ChainableWithSecondType['within'];
type Ordinary = ChainableLike<string, string>['within'];
declare let m: Merged;
m((p: string) => null!);
m((p: string, e: string) => null!);
m((p) => null!);
m((p, e) => null!);
declare let o: Ordinary;
o((p: string) => null!);
o((p: string, e: string) => null!);
o((p) => null!);
o((p, e) => null!);
//// [mergeTwoInterfaces3.js]
m(function (p) { return null; });
m(function (p, e) { return null; });
m(function (p) { return null; });
m(function (p, e) { return null; });
o(function (p) { return null; });
o(function (p, e) { return null; });
o(function (p) { return null; });
o(function (p, e) { return null; });

Просмотреть файл

@ -0,0 +1,122 @@
//// [tests/cases/conformance/interfaces/declarationMerging/mergeTwoInterfaces3.ts] ////
=== mergeTwoInterfaces3.ts ===
interface Chainable<Subject = any> {
>Chainable : Symbol(Chainable, Decl(mergeTwoInterfaces3.ts, 0, 0), Decl(mergeTwoInterfaces3.ts, 2, 1))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 0, 20), Decl(mergeTwoInterfaces3.ts, 4, 20))
within(fn: (prevSubject: Subject) => Chainable<Subject>): Chainable<Subject>;
>within : Symbol(Chainable.within, Decl(mergeTwoInterfaces3.ts, 0, 36), Decl(mergeTwoInterfaces3.ts, 4, 59))
>fn : Symbol(fn, Decl(mergeTwoInterfaces3.ts, 1, 11))
>prevSubject : Symbol(prevSubject, Decl(mergeTwoInterfaces3.ts, 1, 16))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 0, 20), Decl(mergeTwoInterfaces3.ts, 4, 20))
>Chainable : Symbol(Chainable, Decl(mergeTwoInterfaces3.ts, 0, 0), Decl(mergeTwoInterfaces3.ts, 2, 1))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 0, 20), Decl(mergeTwoInterfaces3.ts, 4, 20))
>Chainable : Symbol(Chainable, Decl(mergeTwoInterfaces3.ts, 0, 0), Decl(mergeTwoInterfaces3.ts, 2, 1))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 0, 20), Decl(mergeTwoInterfaces3.ts, 4, 20))
}
interface Chainable<Subject = any, ExtraType = undefined> {
>Chainable : Symbol(Chainable, Decl(mergeTwoInterfaces3.ts, 0, 0), Decl(mergeTwoInterfaces3.ts, 2, 1))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 0, 20), Decl(mergeTwoInterfaces3.ts, 4, 20))
>ExtraType : Symbol(ExtraType, Decl(mergeTwoInterfaces3.ts, 4, 34))
within(fn: (prevSubject: Subject, extra: ExtraType) => Chainable<Subject>): Chainable<Subject, ExtraType>;
>within : Symbol(Chainable.within, Decl(mergeTwoInterfaces3.ts, 0, 36), Decl(mergeTwoInterfaces3.ts, 4, 59))
>fn : Symbol(fn, Decl(mergeTwoInterfaces3.ts, 5, 11))
>prevSubject : Symbol(prevSubject, Decl(mergeTwoInterfaces3.ts, 5, 16))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 0, 20), Decl(mergeTwoInterfaces3.ts, 4, 20))
>extra : Symbol(extra, Decl(mergeTwoInterfaces3.ts, 5, 37))
>ExtraType : Symbol(ExtraType, Decl(mergeTwoInterfaces3.ts, 4, 34))
>Chainable : Symbol(Chainable, Decl(mergeTwoInterfaces3.ts, 0, 0), Decl(mergeTwoInterfaces3.ts, 2, 1))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 0, 20), Decl(mergeTwoInterfaces3.ts, 4, 20))
>Chainable : Symbol(Chainable, Decl(mergeTwoInterfaces3.ts, 0, 0), Decl(mergeTwoInterfaces3.ts, 2, 1))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 0, 20), Decl(mergeTwoInterfaces3.ts, 4, 20))
>ExtraType : Symbol(ExtraType, Decl(mergeTwoInterfaces3.ts, 4, 34))
}
interface ChainableLike<Subject = any, ExtraType = undefined> {
>ChainableLike : Symbol(ChainableLike, Decl(mergeTwoInterfaces3.ts, 6, 1))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 8, 24))
>ExtraType : Symbol(ExtraType, Decl(mergeTwoInterfaces3.ts, 8, 38))
within(fn: (prevSubject: Subject) => Chainable<Subject>): Chainable<Subject>;
>within : Symbol(ChainableLike.within, Decl(mergeTwoInterfaces3.ts, 8, 63), Decl(mergeTwoInterfaces3.ts, 9, 81))
>fn : Symbol(fn, Decl(mergeTwoInterfaces3.ts, 9, 11))
>prevSubject : Symbol(prevSubject, Decl(mergeTwoInterfaces3.ts, 9, 16))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 8, 24))
>Chainable : Symbol(Chainable, Decl(mergeTwoInterfaces3.ts, 0, 0), Decl(mergeTwoInterfaces3.ts, 2, 1))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 8, 24))
>Chainable : Symbol(Chainable, Decl(mergeTwoInterfaces3.ts, 0, 0), Decl(mergeTwoInterfaces3.ts, 2, 1))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 8, 24))
within(fn: (prevSubject: Subject, extra: ExtraType) => Chainable<Subject>): Chainable<Subject, ExtraType>;
>within : Symbol(ChainableLike.within, Decl(mergeTwoInterfaces3.ts, 8, 63), Decl(mergeTwoInterfaces3.ts, 9, 81))
>fn : Symbol(fn, Decl(mergeTwoInterfaces3.ts, 10, 11))
>prevSubject : Symbol(prevSubject, Decl(mergeTwoInterfaces3.ts, 10, 16))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 8, 24))
>extra : Symbol(extra, Decl(mergeTwoInterfaces3.ts, 10, 37))
>ExtraType : Symbol(ExtraType, Decl(mergeTwoInterfaces3.ts, 8, 38))
>Chainable : Symbol(Chainable, Decl(mergeTwoInterfaces3.ts, 0, 0), Decl(mergeTwoInterfaces3.ts, 2, 1))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 8, 24))
>Chainable : Symbol(Chainable, Decl(mergeTwoInterfaces3.ts, 0, 0), Decl(mergeTwoInterfaces3.ts, 2, 1))
>Subject : Symbol(Subject, Decl(mergeTwoInterfaces3.ts, 8, 24))
>ExtraType : Symbol(ExtraType, Decl(mergeTwoInterfaces3.ts, 8, 38))
}
type ChainableWithSecondType = Chainable<string, string>;
>ChainableWithSecondType : Symbol(ChainableWithSecondType, Decl(mergeTwoInterfaces3.ts, 11, 1))
>Chainable : Symbol(Chainable, Decl(mergeTwoInterfaces3.ts, 0, 0), Decl(mergeTwoInterfaces3.ts, 2, 1))
type Merged = ChainableWithSecondType['within'];
>Merged : Symbol(Merged, Decl(mergeTwoInterfaces3.ts, 13, 57))
>ChainableWithSecondType : Symbol(ChainableWithSecondType, Decl(mergeTwoInterfaces3.ts, 11, 1))
type Ordinary = ChainableLike<string, string>['within'];
>Ordinary : Symbol(Ordinary, Decl(mergeTwoInterfaces3.ts, 14, 48))
>ChainableLike : Symbol(ChainableLike, Decl(mergeTwoInterfaces3.ts, 6, 1))
declare let m: Merged;
>m : Symbol(m, Decl(mergeTwoInterfaces3.ts, 17, 11))
>Merged : Symbol(Merged, Decl(mergeTwoInterfaces3.ts, 13, 57))
m((p: string) => null!);
>m : Symbol(m, Decl(mergeTwoInterfaces3.ts, 17, 11))
>p : Symbol(p, Decl(mergeTwoInterfaces3.ts, 18, 3))
m((p: string, e: string) => null!);
>m : Symbol(m, Decl(mergeTwoInterfaces3.ts, 17, 11))
>p : Symbol(p, Decl(mergeTwoInterfaces3.ts, 19, 3))
>e : Symbol(e, Decl(mergeTwoInterfaces3.ts, 19, 13))
m((p) => null!);
>m : Symbol(m, Decl(mergeTwoInterfaces3.ts, 17, 11))
>p : Symbol(p, Decl(mergeTwoInterfaces3.ts, 20, 3))
m((p, e) => null!);
>m : Symbol(m, Decl(mergeTwoInterfaces3.ts, 17, 11))
>p : Symbol(p, Decl(mergeTwoInterfaces3.ts, 21, 3))
>e : Symbol(e, Decl(mergeTwoInterfaces3.ts, 21, 5))
declare let o: Ordinary;
>o : Symbol(o, Decl(mergeTwoInterfaces3.ts, 23, 11))
>Ordinary : Symbol(Ordinary, Decl(mergeTwoInterfaces3.ts, 14, 48))
o((p: string) => null!);
>o : Symbol(o, Decl(mergeTwoInterfaces3.ts, 23, 11))
>p : Symbol(p, Decl(mergeTwoInterfaces3.ts, 24, 3))
o((p: string, e: string) => null!);
>o : Symbol(o, Decl(mergeTwoInterfaces3.ts, 23, 11))
>p : Symbol(p, Decl(mergeTwoInterfaces3.ts, 25, 3))
>e : Symbol(e, Decl(mergeTwoInterfaces3.ts, 25, 13))
o((p) => null!);
>o : Symbol(o, Decl(mergeTwoInterfaces3.ts, 23, 11))
>p : Symbol(p, Decl(mergeTwoInterfaces3.ts, 26, 3))
o((p, e) => null!);
>o : Symbol(o, Decl(mergeTwoInterfaces3.ts, 23, 11))
>p : Symbol(p, Decl(mergeTwoInterfaces3.ts, 27, 3))
>e : Symbol(e, Decl(mergeTwoInterfaces3.ts, 27, 5))

Просмотреть файл

@ -0,0 +1,106 @@
//// [tests/cases/conformance/interfaces/declarationMerging/mergeTwoInterfaces3.ts] ////
=== mergeTwoInterfaces3.ts ===
interface Chainable<Subject = any> {
within(fn: (prevSubject: Subject) => Chainable<Subject>): Chainable<Subject>;
>within : { (fn: (prevSubject: Subject) => Chainable<Subject>): Chainable<Subject>; (fn: (prevSubject: Subject, extra: ExtraType) => Chainable<Subject, undefined>): Chainable<Subject, ExtraType>; }
>fn : (prevSubject: Subject) => Chainable<Subject>
>prevSubject : Subject
}
interface Chainable<Subject = any, ExtraType = undefined> {
within(fn: (prevSubject: Subject, extra: ExtraType) => Chainable<Subject>): Chainable<Subject, ExtraType>;
>within : { (fn: (prevSubject: Subject) => Chainable<Subject, undefined>): Chainable<Subject, undefined>; (fn: (prevSubject: Subject, extra: ExtraType) => Chainable<Subject>): Chainable<Subject, ExtraType>; }
>fn : (prevSubject: Subject, extra: ExtraType) => Chainable<Subject>
>prevSubject : Subject
>extra : ExtraType
}
interface ChainableLike<Subject = any, ExtraType = undefined> {
within(fn: (prevSubject: Subject) => Chainable<Subject>): Chainable<Subject>;
>within : { (fn: (prevSubject: Subject) => Chainable<Subject>): Chainable<Subject>; (fn: (prevSubject: Subject, extra: ExtraType) => Chainable<Subject, undefined>): Chainable<Subject, ExtraType>; }
>fn : (prevSubject: Subject) => Chainable<Subject>
>prevSubject : Subject
within(fn: (prevSubject: Subject, extra: ExtraType) => Chainable<Subject>): Chainable<Subject, ExtraType>;
>within : { (fn: (prevSubject: Subject) => Chainable<Subject, undefined>): Chainable<Subject, undefined>; (fn: (prevSubject: Subject, extra: ExtraType) => Chainable<Subject>): Chainable<Subject, ExtraType>; }
>fn : (prevSubject: Subject, extra: ExtraType) => Chainable<Subject>
>prevSubject : Subject
>extra : ExtraType
}
type ChainableWithSecondType = Chainable<string, string>;
>ChainableWithSecondType : Chainable<string, string>
type Merged = ChainableWithSecondType['within'];
>Merged : { (fn: (prevSubject: string) => Chainable<string, undefined>): Chainable<string, undefined>; (fn: (prevSubject: string, extra: string) => Chainable<string, undefined>): Chainable<string, string>; }
type Ordinary = ChainableLike<string, string>['within'];
>Ordinary : { (fn: (prevSubject: string) => Chainable<string, undefined>): Chainable<string, undefined>; (fn: (prevSubject: string, extra: string) => Chainable<string, undefined>): Chainable<string, string>; }
declare let m: Merged;
>m : { (fn: (prevSubject: string) => Chainable<string, undefined>): Chainable<string, undefined>; (fn: (prevSubject: string, extra: string) => Chainable<string, undefined>): Chainable<string, string>; }
m((p: string) => null!);
>m((p: string) => null!) : Chainable<string, string>
>m : { (fn: (prevSubject: string) => Chainable<string, undefined>): Chainable<string, undefined>; (fn: (prevSubject: string, extra: string) => Chainable<string, undefined>): Chainable<string, string>; }
>(p: string) => null! : (p: string) => any
>p : string
>null! : null
m((p: string, e: string) => null!);
>m((p: string, e: string) => null!) : Chainable<string, string>
>m : { (fn: (prevSubject: string) => Chainable<string, undefined>): Chainable<string, undefined>; (fn: (prevSubject: string, extra: string) => Chainable<string, undefined>): Chainable<string, string>; }
>(p: string, e: string) => null! : (p: string, e: string) => any
>p : string
>e : string
>null! : null
m((p) => null!);
>m((p) => null!) : Chainable<string, string>
>m : { (fn: (prevSubject: string) => Chainable<string, undefined>): Chainable<string, undefined>; (fn: (prevSubject: string, extra: string) => Chainable<string, undefined>): Chainable<string, string>; }
>(p) => null! : (p: string) => any
>p : string
>null! : null
m((p, e) => null!);
>m((p, e) => null!) : Chainable<string, string>
>m : { (fn: (prevSubject: string) => Chainable<string, undefined>): Chainable<string, undefined>; (fn: (prevSubject: string, extra: string) => Chainable<string, undefined>): Chainable<string, string>; }
>(p, e) => null! : (p: string, e: string) => any
>p : string
>e : string
>null! : null
declare let o: Ordinary;
>o : { (fn: (prevSubject: string) => Chainable<string, undefined>): Chainable<string, undefined>; (fn: (prevSubject: string, extra: string) => Chainable<string, undefined>): Chainable<string, string>; }
o((p: string) => null!);
>o((p: string) => null!) : Chainable<string, undefined>
>o : { (fn: (prevSubject: string) => Chainable<string, undefined>): Chainable<string, undefined>; (fn: (prevSubject: string, extra: string) => Chainable<string, undefined>): Chainable<string, string>; }
>(p: string) => null! : (p: string) => any
>p : string
>null! : null
o((p: string, e: string) => null!);
>o((p: string, e: string) => null!) : Chainable<string, string>
>o : { (fn: (prevSubject: string) => Chainable<string, undefined>): Chainable<string, undefined>; (fn: (prevSubject: string, extra: string) => Chainable<string, undefined>): Chainable<string, string>; }
>(p: string, e: string) => null! : (p: string, e: string) => any
>p : string
>e : string
>null! : null
o((p) => null!);
>o((p) => null!) : Chainable<string, undefined>
>o : { (fn: (prevSubject: string) => Chainable<string, undefined>): Chainable<string, undefined>; (fn: (prevSubject: string, extra: string) => Chainable<string, undefined>): Chainable<string, string>; }
>(p) => null! : (p: string) => any
>p : string
>null! : null
o((p, e) => null!);
>o((p, e) => null!) : Chainable<string, string>
>o : { (fn: (prevSubject: string) => Chainable<string, undefined>): Chainable<string, undefined>; (fn: (prevSubject: string, extra: string) => Chainable<string, undefined>): Chainable<string, string>; }
>(p, e) => null! : (p: any, e: any) => any
>p : any
>e : any
>null! : null

Просмотреть файл

@ -0,0 +1,28 @@
interface Chainable<Subject = any> {
within(fn: (prevSubject: Subject) => Chainable<Subject>): Chainable<Subject>;
}
interface Chainable<Subject = any, ExtraType = undefined> {
within(fn: (prevSubject: Subject, extra: ExtraType) => Chainable<Subject>): Chainable<Subject, ExtraType>;
}
interface ChainableLike<Subject = any, ExtraType = undefined> {
within(fn: (prevSubject: Subject) => Chainable<Subject>): Chainable<Subject>;
within(fn: (prevSubject: Subject, extra: ExtraType) => Chainable<Subject>): Chainable<Subject, ExtraType>;
}
type ChainableWithSecondType = Chainable<string, string>;
type Merged = ChainableWithSecondType['within'];
type Ordinary = ChainableLike<string, string>['within'];
declare let m: Merged;
m((p: string) => null!);
m((p: string, e: string) => null!);
m((p) => null!);
m((p, e) => null!);
declare let o: Ordinary;
o((p: string) => null!);
o((p: string, e: string) => null!);
o((p) => null!);
o((p, e) => null!);