Report generic rest parameters as unreliable variance positions (#33020)

* Report generic rest parameters as unreliable variance positions

* Add example from discussion on #30301
This commit is contained in:
Wesley Wigham 2019-10-30 13:54:39 -07:00 committed by GitHub
parent 5e0fbc677a
commit 7b02c635b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 488 additions and 4 deletions

View File

@ -13919,7 +13919,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;
@ -13943,7 +13943,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;
@ -13966,6 +13967,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;
@ -14013,7 +14017,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) {
@ -15967,7 +15971,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 {

View File

@ -0,0 +1,42 @@
//// [aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts]
// the type printback for every `test` below should be "y"
type ExtendedMapper<HandledInputT, OutputT, ArgsT extends any[]> = (name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT;
type a = ExtendedMapper<any, any, [any]>;
type b = ExtendedMapper<any, any, any[]>;
type test = a extends b ? "y" : "n"
let check: test = "y";
type ExtendedMapper1<HandledInputT, OutputT, ArgsT extends any[]> = (
(name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT
);
type a1 = ExtendedMapper1<any, any, [any]>;
type b1 = ExtendedMapper1<any, any, any[]>;
type test1 = a1 extends b1 ? "y" : "n"
let check1: test1 = "y";
type ExtendedMapper2<HandledInputT, OutputT, ArgsT extends any[]> = (
{x:(name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT}["x"]
);
type a2 = ExtendedMapper2<any, any, [any]>;
type b2 = ExtendedMapper2<any, any, any[]>;
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";

View File

@ -0,0 +1,121 @@
=== tests/cases/compiler/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts ===
// the type printback for every `test` below should be "y"
type ExtendedMapper<HandledInputT, OutputT, ArgsT extends any[]> = (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<any, any, [any]>;
>a : Symbol(a, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 2, 134))
>ExtendedMapper : Symbol(ExtendedMapper, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 0, 0))
type b = ExtendedMapper<any, any, any[]>;
>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<HandledInputT, OutputT, ArgsT extends any[]> = (
>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<any, any, [any]>;
>a1 : Symbol(a1, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 11, 2))
>ExtendedMapper1 : Symbol(ExtendedMapper1, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 6, 22))
type b1 = ExtendedMapper1<any, any, any[]>;
>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<HandledInputT, OutputT, ArgsT extends any[]> = (
>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<any, any, [any]>;
>a2 : Symbol(a2, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 20, 2))
>ExtendedMapper2 : Symbol(ExtendedMapper2, Decl(aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts, 16, 24))
type b2 = ExtendedMapper2<any, any, any[]>;
>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))

View File

@ -0,0 +1,89 @@
=== tests/cases/compiler/aliasOfGenericFunctionWithRestBehavedSameAsUnaliased.ts ===
// the type printback for every `test` below should be "y"
type ExtendedMapper<HandledInputT, OutputT, ArgsT extends any[]> = (name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT;
>ExtendedMapper : ExtendedMapper<HandledInputT, OutputT, ArgsT>
>name : string
>mixed : HandledInputT
>args : ArgsT
type a = ExtendedMapper<any, any, [any]>;
>a : ExtendedMapper<any, any, [any]>
type b = ExtendedMapper<any, any, any[]>;
>b : ExtendedMapper<any, any, any[]>
type test = a extends b ? "y" : "n"
>test : "y"
let check: test = "y";
>check : "y"
>"y" : "y"
type ExtendedMapper1<HandledInputT, OutputT, ArgsT extends any[]> = (
>ExtendedMapper1 : ExtendedMapper1<HandledInputT, OutputT, ArgsT>
(name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT
>name : string
>mixed : HandledInputT
>args : ArgsT
);
type a1 = ExtendedMapper1<any, any, [any]>;
>a1 : ExtendedMapper1<any, any, [any]>
type b1 = ExtendedMapper1<any, any, any[]>;
>b1 : ExtendedMapper1<any, any, any[]>
type test1 = a1 extends b1 ? "y" : "n"
>test1 : "y"
let check1: test1 = "y";
>check1 : "y"
>"y" : "y"
type ExtendedMapper2<HandledInputT, OutputT, ArgsT extends any[]> = (
>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<any, any, [any]>;
>a2 : (name: string, mixed: any, args_0: any) => any
type b2 = ExtendedMapper2<any, any, any[]>;
>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"

View File

@ -0,0 +1,38 @@
//// [lambdaParameterWithTupleArgsHasCorrectAssignability.ts]
type MyTupleItem = {};
type MyTuple = [MyTupleItem, ...MyTupleItem[]];
type GenericFunction<T extends MyTuple> = (...fromArgs: T) => void;
class GenericClass<T extends MyTuple> {
from: GenericFunction<T> | undefined;
}
function createClass<T extends MyTuple>(f: GenericFunction<T>): GenericClass<T> {
return new GenericClass<T>(/* ... 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); }));

View File

@ -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<T extends MyTuple> = (...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<T extends MyTuple> {
>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<T> | 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<T extends MyTuple>(f: GenericFunction<T>): GenericClass<T> {
>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<T>(/* ... 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, --, --))

View File

@ -0,0 +1,64 @@
=== tests/cases/compiler/lambdaParameterWithTupleArgsHasCorrectAssignability.ts ===
type MyTupleItem = {};
>MyTupleItem : MyTupleItem
type MyTuple = [MyTupleItem, ...MyTupleItem[]];
>MyTuple : MyTuple
type GenericFunction<T extends MyTuple> = (...fromArgs: T) => void;
>GenericFunction : GenericFunction<T>
>fromArgs : T
class GenericClass<T extends MyTuple> {
>GenericClass : GenericClass<T>
from: GenericFunction<T> | undefined;
>from : GenericFunction<T> | undefined
}
function createClass<T extends MyTuple>(f: GenericFunction<T>): GenericClass<T> {
>createClass : <T extends MyTuple>(f: GenericFunction<T>) => GenericClass<T>
>f : GenericFunction<T>
return new GenericClass<T>(/* ... use f */);
>new GenericClass<T>(/* ... use f */) : GenericClass<T>
>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 : <T extends MyTuple>(f: GenericFunction<T>) => GenericClass<T>
>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 : <T extends MyTuple>(f: GenericFunction<T>) => GenericClass<T>
>(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

View File

@ -0,0 +1,33 @@
// @strict: true
// the type printback for every `test` below should be "y"
type ExtendedMapper<HandledInputT, OutputT, ArgsT extends any[]> = (name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT;
type a = ExtendedMapper<any, any, [any]>;
type b = ExtendedMapper<any, any, any[]>;
type test = a extends b ? "y" : "n"
let check: test = "y";
type ExtendedMapper1<HandledInputT, OutputT, ArgsT extends any[]> = (
(name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT
);
type a1 = ExtendedMapper1<any, any, [any]>;
type b1 = ExtendedMapper1<any, any, any[]>;
type test1 = a1 extends b1 ? "y" : "n"
let check1: test1 = "y";
type ExtendedMapper2<HandledInputT, OutputT, ArgsT extends any[]> = (
{x:(name : string, mixed : HandledInputT, ...args : ArgsT) => OutputT}["x"]
);
type a2 = ExtendedMapper2<any, any, [any]>;
type b2 = ExtendedMapper2<any, any, any[]>;
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";

View File

@ -0,0 +1,21 @@
// @strict: true
type MyTupleItem = {};
type MyTuple = [MyTupleItem, ...MyTupleItem[]];
type GenericFunction<T extends MyTuple> = (...fromArgs: T) => void;
class GenericClass<T extends MyTuple> {
from: GenericFunction<T> | undefined;
}
function createClass<T extends MyTuple>(f: GenericFunction<T>): GenericClass<T> {
return new GenericClass<T>(/* ... 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)));