diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a8a19743ae187..7aeb25227e3ee 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13900,7 +13900,7 @@ namespace ts { target: Signature, ignoreReturnTypes: boolean): boolean { return compareSignaturesRelated(source, target, CallbackCheck.None, ignoreReturnTypes, /*reportErrors*/ false, - /*errorReporter*/ undefined, /*errorReporter*/ undefined, compareTypesAssignable) !== Ternary.False; + /*errorReporter*/ undefined, /*errorReporter*/ undefined, compareTypesAssignable, /*reportUnreliableMarkers*/ undefined) !== Ternary.False; } type ErrorReporter = (message: DiagnosticMessage, arg0?: string, arg1?: string) => void; @@ -13924,7 +13924,8 @@ namespace ts { reportErrors: boolean, errorReporter: ErrorReporter | undefined, incompatibleErrorReporter: ((source: Type, target: Type) => void) | undefined, - compareTypes: TypeComparer): Ternary { + compareTypes: TypeComparer, + reportUnreliableMarkers: TypeMapper | undefined): Ternary { // TODO (drosen): De-duplicate code between related functions. if (source === target) { return Ternary.True; @@ -13947,6 +13948,9 @@ namespace ts { const sourceCount = getParameterCount(source); const sourceRestType = getNonArrayRestType(source); const targetRestType = getNonArrayRestType(target); + if (sourceRestType || targetRestType) { + void instantiateType(sourceRestType || targetRestType, reportUnreliableMarkers); + } if (sourceRestType && targetRestType && sourceCount !== targetCount) { // We're not able to relate misaligned complex rest parameters return Ternary.False; @@ -13994,7 +13998,7 @@ namespace ts { (getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable); const related = callbacks ? // TODO: GH#18217 It will work if they're both `undefined`, but not if only one is - compareSignaturesRelated(targetSig!, sourceSig!, strictVariance ? CallbackCheck.Strict : CallbackCheck.Bivariant, /*ignoreReturnTypes*/ false, reportErrors, errorReporter, incompatibleErrorReporter, compareTypes) : + compareSignaturesRelated(targetSig!, sourceSig!, strictVariance ? CallbackCheck.Strict : CallbackCheck.Bivariant, /*ignoreReturnTypes*/ false, reportErrors, errorReporter, incompatibleErrorReporter, compareTypes, reportUnreliableMarkers) : !callbackCheck && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors); if (!related) { if (reportErrors) { @@ -15948,7 +15952,7 @@ namespace ts { */ function signatureRelatedTo(source: Signature, target: Signature, erase: boolean, reportErrors: boolean, incompatibleReporter: (source: Type, target: Type) => void): Ternary { return compareSignaturesRelated(erase ? getErasedSignature(source) : source, erase ? getErasedSignature(target) : target, - CallbackCheck.None, /*ignoreReturnTypes*/ false, reportErrors, reportError, incompatibleReporter, isRelatedTo); + CallbackCheck.None, /*ignoreReturnTypes*/ false, reportErrors, reportError, incompatibleReporter, isRelatedTo, reportUnreliableMarkers); } function signaturesIdenticalTo(source: Type, target: Type, kind: SignatureKind): Ternary { diff --git a/tests/baselines/reference/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.js b/tests/baselines/reference/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.js new file mode 100644 index 0000000000000..567b75e850241 --- /dev/null +++ b/tests/baselines/reference/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.js @@ -0,0 +1,42 @@ +//// [aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts] +// the type printback for every `test` below should be "y" + +type ExtendedMapper = (name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT; +type a = ExtendedMapper; +type b = ExtendedMapper; +type test = a extends b ? "y" : "n" +let check: test = "y"; + + +type ExtendedMapper1 = ( + (name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT +); + +type a1 = ExtendedMapper1; +type b1 = ExtendedMapper1; +type test1 = a1 extends b1 ? "y" : "n" +let check1: test1 = "y"; + +type ExtendedMapper2 = ( + {x:(name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT}["x"] +); + +type a2 = ExtendedMapper2; +type b2 = ExtendedMapper2; +type test2 = a2 extends b2 ? "y" : "n" +let check2: test2 = "y"; + +type a3 = (name: string, mixed: any, args_0: any) => any +type b3 = (name: string, mixed: any, ...args: any[]) => any + +type test3 = a3 extends b3 ? "y" : "n" +let check3: test3 = "y"; + + +//// [aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.js] +"use strict"; +// the type printback for every `test` below should be "y" +var check = "y"; +var check1 = "y"; +var check2 = "y"; +var check3 = "y"; diff --git a/tests/baselines/reference/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.symbols b/tests/baselines/reference/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.symbols new file mode 100644 index 0000000000000..2978901d38595 --- /dev/null +++ b/tests/baselines/reference/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.symbols @@ -0,0 +1,121 @@ +=== tests/cases/compiler/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts === +// the type printback for every `test` below should be "y" + +type ExtendedMapper = (name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT; +>ExtendedMapper : Symbol(ExtendedMapper, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 0, 0)) +>HandledInputT : Symbol(HandledInputT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 2, 20)) +>OutputT : Symbol(OutputT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 2, 34)) +>ArgsT : Symbol(ArgsT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 2, 43)) +>name : Symbol(name, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 2, 68)) +>mixed : Symbol(mixed, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 2, 82)) +>HandledInputT : Symbol(HandledInputT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 2, 20)) +>args : Symbol(args, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 2, 105)) +>ArgsT : Symbol(ArgsT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 2, 43)) +>OutputT : Symbol(OutputT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 2, 34)) + +type a = ExtendedMapper; +>a : Symbol(a, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 2, 134)) +>ExtendedMapper : Symbol(ExtendedMapper, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 0, 0)) + +type b = ExtendedMapper; +>b : Symbol(b, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 3, 41)) +>ExtendedMapper : Symbol(ExtendedMapper, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 0, 0)) + +type test = a extends b ? "y" : "n" +>test : Symbol(test, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 4, 41)) +>a : Symbol(a, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 2, 134)) +>b : Symbol(b, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 3, 41)) + +let check: test = "y"; +>check : Symbol(check, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 6, 3)) +>test : Symbol(test, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 4, 41)) + + +type ExtendedMapper1 = ( +>ExtendedMapper1 : Symbol(ExtendedMapper1, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 6, 22)) +>HandledInputT : Symbol(HandledInputT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 9, 21)) +>OutputT : Symbol(OutputT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 9, 35)) +>ArgsT : Symbol(ArgsT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 9, 44)) + + (name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT +>name : Symbol(name, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 10, 5)) +>mixed : Symbol(mixed, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 10, 19)) +>HandledInputT : Symbol(HandledInputT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 9, 21)) +>args : Symbol(args, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 10, 42)) +>ArgsT : Symbol(ArgsT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 9, 44)) +>OutputT : Symbol(OutputT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 9, 35)) + +); + +type a1 = ExtendedMapper1; +>a1 : Symbol(a1, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 11, 2)) +>ExtendedMapper1 : Symbol(ExtendedMapper1, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 6, 22)) + +type b1 = ExtendedMapper1; +>b1 : Symbol(b1, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 13, 43)) +>ExtendedMapper1 : Symbol(ExtendedMapper1, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 6, 22)) + +type test1 = a1 extends b1 ? "y" : "n" +>test1 : Symbol(test1, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 14, 43)) +>a1 : Symbol(a1, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 11, 2)) +>b1 : Symbol(b1, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 13, 43)) + +let check1: test1 = "y"; +>check1 : Symbol(check1, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 16, 3)) +>test1 : Symbol(test1, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 14, 43)) + +type ExtendedMapper2 = ( +>ExtendedMapper2 : Symbol(ExtendedMapper2, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 16, 24)) +>HandledInputT : Symbol(HandledInputT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 18, 21)) +>OutputT : Symbol(OutputT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 18, 35)) +>ArgsT : Symbol(ArgsT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 18, 44)) + + {x:(name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT}["x"] +>x : Symbol(x, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 19, 5)) +>name : Symbol(name, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 19, 8)) +>mixed : Symbol(mixed, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 19, 22)) +>HandledInputT : Symbol(HandledInputT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 18, 21)) +>args : Symbol(args, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 19, 45)) +>ArgsT : Symbol(ArgsT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 18, 44)) +>OutputT : Symbol(OutputT, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 18, 35)) + +); + +type a2 = ExtendedMapper2; +>a2 : Symbol(a2, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 20, 2)) +>ExtendedMapper2 : Symbol(ExtendedMapper2, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 16, 24)) + +type b2 = ExtendedMapper2; +>b2 : Symbol(b2, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 22, 43)) +>ExtendedMapper2 : Symbol(ExtendedMapper2, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 16, 24)) + +type test2 = a2 extends b2 ? "y" : "n" +>test2 : Symbol(test2, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 23, 43)) +>a2 : Symbol(a2, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 20, 2)) +>b2 : Symbol(b2, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 22, 43)) + +let check2: test2 = "y"; +>check2 : Symbol(check2, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 25, 3)) +>test2 : Symbol(test2, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 23, 43)) + +type a3 = (name: string, mixed: any, args_0: any) => any +>a3 : Symbol(a3, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 25, 24)) +>name : Symbol(name, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 27, 11)) +>mixed : Symbol(mixed, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 27, 24)) +>args_0 : Symbol(args_0, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 27, 36)) + +type b3 = (name: string, mixed: any, ...args: any[]) => any +>b3 : Symbol(b3, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 27, 56)) +>name : Symbol(name, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 28, 11)) +>mixed : Symbol(mixed, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 28, 24)) +>args : Symbol(args, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 28, 36)) + +type test3 = a3 extends b3 ? "y" : "n" +>test3 : Symbol(test3, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 28, 59)) +>a3 : Symbol(a3, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 25, 24)) +>b3 : Symbol(b3, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 27, 56)) + +let check3: test3 = "y"; +>check3 : Symbol(check3, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 31, 3)) +>test3 : Symbol(test3, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 28, 59)) + diff --git a/tests/baselines/reference/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.types b/tests/baselines/reference/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.types new file mode 100644 index 0000000000000..18858801f26f6 --- /dev/null +++ b/tests/baselines/reference/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.types @@ -0,0 +1,89 @@ +=== tests/cases/compiler/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts === +// the type printback for every `test` below should be "y" + +type ExtendedMapper = (name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT; +>ExtendedMapper : ExtendedMapper +>name : string +>mixed : HandledInputT +>args : ArgsT + +type a = ExtendedMapper; +>a : ExtendedMapper + +type b = ExtendedMapper; +>b : ExtendedMapper + +type test = a extends b ? "y" : "n" +>test : "y" + +let check: test = "y"; +>check : "y" +>"y" : "y" + + +type ExtendedMapper1 = ( +>ExtendedMapper1 : ExtendedMapper1 + + (name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT +>name : string +>mixed : HandledInputT +>args : ArgsT + +); + +type a1 = ExtendedMapper1; +>a1 : ExtendedMapper1 + +type b1 = ExtendedMapper1; +>b1 : ExtendedMapper1 + +type test1 = a1 extends b1 ? "y" : "n" +>test1 : "y" + +let check1: test1 = "y"; +>check1 : "y" +>"y" : "y" + +type ExtendedMapper2 = ( +>ExtendedMapper2 : (name: string, mixed: HandledInputT, ...args: ArgsT) => OutputT + + {x:(name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT}["x"] +>x : (name: string, mixed: HandledInputT, ...args: ArgsT) => OutputT +>name : string +>mixed : HandledInputT +>args : ArgsT + +); + +type a2 = ExtendedMapper2; +>a2 : (name: string, mixed: any, args_0: any) => any + +type b2 = ExtendedMapper2; +>b2 : (name: string, mixed: any, ...args: any[]) => any + +type test2 = a2 extends b2 ? "y" : "n" +>test2 : "y" + +let check2: test2 = "y"; +>check2 : "y" +>"y" : "y" + +type a3 = (name: string, mixed: any, args_0: any) => any +>a3 : a3 +>name : string +>mixed : any +>args_0 : any + +type b3 = (name: string, mixed: any, ...args: any[]) => any +>b3 : b3 +>name : string +>mixed : any +>args : any[] + +type test3 = a3 extends b3 ? "y" : "n" +>test3 : "y" + +let check3: test3 = "y"; +>check3 : "y" +>"y" : "y" + diff --git a/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.js b/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.js new file mode 100644 index 0000000000000..31e5ce1ca17c4 --- /dev/null +++ b/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.js @@ -0,0 +1,38 @@ +//// [lambdaParameterWithTupleArgsHasCorrectAssignability.ts] +type MyTupleItem = {}; +type MyTuple = [MyTupleItem, ...MyTupleItem[]]; + +type GenericFunction = (...fromArgs: T) => void; + +class GenericClass { + from: GenericFunction | undefined; +} + +function createClass(f: GenericFunction): GenericClass { + return new GenericClass(/* ... use f */); +} + +function consumeClass(c: GenericClass<[string, boolean]>) { } + +// should work +consumeClass(createClass(str => console.log(str.length))); + +// should work +consumeClass(createClass((str, _unused_num) => console.log(str.length))); + + +//// [lambdaParameterWithTupleArgsHasCorrectAssignability.js] +"use strict"; +var GenericClass = /** @class */ (function () { + function GenericClass() { + } + return GenericClass; +}()); +function createClass(f) { + return new GenericClass( /* ... use f */); +} +function consumeClass(c) { } +// should work +consumeClass(createClass(function (str) { return console.log(str.length); })); +// should work +consumeClass(createClass(function (str, _unused_num) { return console.log(str.length); })); diff --git a/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.symbols b/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.symbols new file mode 100644 index 0000000000000..1b113924534d0 --- /dev/null +++ b/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.symbols @@ -0,0 +1,72 @@ +=== tests/cases/compiler/lambdaParameterWithTupleArgsHasCorrectAssignability.ts === +type MyTupleItem = {}; +>MyTupleItem : Symbol(MyTupleItem, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 0, 0)) + +type MyTuple = [MyTupleItem, ...MyTupleItem[]]; +>MyTuple : Symbol(MyTuple, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 0, 22)) +>MyTupleItem : Symbol(MyTupleItem, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 0, 0)) +>MyTupleItem : Symbol(MyTupleItem, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 0, 0)) + +type GenericFunction = (...fromArgs: T) => void; +>GenericFunction : Symbol(GenericFunction, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 1, 47)) +>T : Symbol(T, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 3, 21)) +>MyTuple : Symbol(MyTuple, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 0, 22)) +>fromArgs : Symbol(fromArgs, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 3, 43)) +>T : Symbol(T, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 3, 21)) + +class GenericClass { +>GenericClass : Symbol(GenericClass, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 3, 67)) +>T : Symbol(T, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 5, 19)) +>MyTuple : Symbol(MyTuple, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 0, 22)) + + from: GenericFunction | undefined; +>from : Symbol(GenericClass.from, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 5, 39)) +>GenericFunction : Symbol(GenericFunction, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 1, 47)) +>T : Symbol(T, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 5, 19)) +} + +function createClass(f: GenericFunction): GenericClass { +>createClass : Symbol(createClass, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 7, 1)) +>T : Symbol(T, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 9, 21)) +>MyTuple : Symbol(MyTuple, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 0, 22)) +>f : Symbol(f, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 9, 40)) +>GenericFunction : Symbol(GenericFunction, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 1, 47)) +>T : Symbol(T, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 9, 21)) +>GenericClass : Symbol(GenericClass, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 3, 67)) +>T : Symbol(T, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 9, 21)) + + return new GenericClass(/* ... use f */); +>GenericClass : Symbol(GenericClass, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 3, 67)) +>T : Symbol(T, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 9, 21)) +} + +function consumeClass(c: GenericClass<[string, boolean]>) { } +>consumeClass : Symbol(consumeClass, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 11, 1)) +>c : Symbol(c, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 13, 22)) +>GenericClass : Symbol(GenericClass, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 3, 67)) + +// should work +consumeClass(createClass(str => console.log(str.length))); +>consumeClass : Symbol(consumeClass, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 11, 1)) +>createClass : Symbol(createClass, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 7, 1)) +>str : Symbol(str, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 16, 25)) +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>str.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) +>str : Symbol(str, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 16, 25)) +>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) + +// should work +consumeClass(createClass((str, _unused_num) => console.log(str.length))); +>consumeClass : Symbol(consumeClass, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 11, 1)) +>createClass : Symbol(createClass, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 7, 1)) +>str : Symbol(str, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 19, 26)) +>_unused_num : Symbol(_unused_num, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 19, 30)) +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>str.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) +>str : Symbol(str, Decl(lambdaParameterWithTupleArgsHasCorrectAssignability.ts, 19, 26)) +>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) + diff --git a/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.types b/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.types new file mode 100644 index 0000000000000..eeb88b9bd1f97 --- /dev/null +++ b/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.types @@ -0,0 +1,64 @@ +=== tests/cases/compiler/lambdaParameterWithTupleArgsHasCorrectAssignability.ts === +type MyTupleItem = {}; +>MyTupleItem : MyTupleItem + +type MyTuple = [MyTupleItem, ...MyTupleItem[]]; +>MyTuple : MyTuple + +type GenericFunction = (...fromArgs: T) => void; +>GenericFunction : GenericFunction +>fromArgs : T + +class GenericClass { +>GenericClass : GenericClass + + from: GenericFunction | undefined; +>from : GenericFunction | undefined +} + +function createClass(f: GenericFunction): GenericClass { +>createClass : (f: GenericFunction) => GenericClass +>f : GenericFunction + + return new GenericClass(/* ... use f */); +>new GenericClass(/* ... use f */) : GenericClass +>GenericClass : typeof GenericClass +} + +function consumeClass(c: GenericClass<[string, boolean]>) { } +>consumeClass : (c: GenericClass<[string, boolean]>) => void +>c : GenericClass<[string, boolean]> + +// should work +consumeClass(createClass(str => console.log(str.length))); +>consumeClass(createClass(str => console.log(str.length))) : void +>consumeClass : (c: GenericClass<[string, boolean]>) => void +>createClass(str => console.log(str.length)) : GenericClass<[string]> +>createClass : (f: GenericFunction) => GenericClass +>str => console.log(str.length) : (str: string) => void +>str : string +>console.log(str.length) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>str.length : number +>str : string +>length : number + +// should work +consumeClass(createClass((str, _unused_num) => console.log(str.length))); +>consumeClass(createClass((str, _unused_num) => console.log(str.length))) : void +>consumeClass : (c: GenericClass<[string, boolean]>) => void +>createClass((str, _unused_num) => console.log(str.length)) : GenericClass<[string, boolean]> +>createClass : (f: GenericFunction) => GenericClass +>(str, _unused_num) => console.log(str.length) : (str: string, _unused_num: boolean) => void +>str : string +>_unused_num : boolean +>console.log(str.length) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>str.length : number +>str : string +>length : number + diff --git a/tests/cases/compiler/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts b/tests/cases/compiler/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts new file mode 100644 index 0000000000000..b581d7f87854b --- /dev/null +++ b/tests/cases/compiler/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts @@ -0,0 +1,33 @@ +// @strict: true +// the type printback for every `test` below should be "y" + +type ExtendedMapper = (name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT; +type a = ExtendedMapper; +type b = ExtendedMapper; +type test = a extends b ? "y" : "n" +let check: test = "y"; + + +type ExtendedMapper1 = ( + (name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT +); + +type a1 = ExtendedMapper1; +type b1 = ExtendedMapper1; +type test1 = a1 extends b1 ? "y" : "n" +let check1: test1 = "y"; + +type ExtendedMapper2 = ( + {x:(name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT}["x"] +); + +type a2 = ExtendedMapper2; +type b2 = ExtendedMapper2; +type test2 = a2 extends b2 ? "y" : "n" +let check2: test2 = "y"; + +type a3 = (name: string, mixed: any, args_0: any) => any +type b3 = (name: string, mixed: any, ...args: any[]) => any + +type test3 = a3 extends b3 ? "y" : "n" +let check3: test3 = "y"; diff --git a/tests/cases/compiler/lambdaParameterWithTupleArgsHasCorrectAssignability.ts b/tests/cases/compiler/lambdaParameterWithTupleArgsHasCorrectAssignability.ts new file mode 100644 index 0000000000000..e71c6226b49b7 --- /dev/null +++ b/tests/cases/compiler/lambdaParameterWithTupleArgsHasCorrectAssignability.ts @@ -0,0 +1,21 @@ +// @strict: true +type MyTupleItem = {}; +type MyTuple = [MyTupleItem, ...MyTupleItem[]]; + +type GenericFunction = (...fromArgs: T) => void; + +class GenericClass { + from: GenericFunction | undefined; +} + +function createClass(f: GenericFunction): GenericClass { + return new GenericClass(/* ... use f */); +} + +function consumeClass(c: GenericClass<[string, boolean]>) { } + +// should work +consumeClass(createClass(str => console.log(str.length))); + +// should work +consumeClass(createClass((str, _unused_num) => console.log(str.length)));