mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #25843 from Microsoft/port25817
Port #25817 to release-3.0
This commit is contained in:
+22
-22
@@ -10493,9 +10493,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
const sourceCount = getParameterCount(source);
|
||||
const sourceRestTypeParameter = getRestTypeParameter(source);
|
||||
const targetRestTypeParameter = sourceRestTypeParameter ? getRestTypeParameter(target) : undefined;
|
||||
if (sourceRestTypeParameter && !(targetRestTypeParameter && sourceCount === targetCount)) {
|
||||
const sourceGenericRestType = getGenericRestType(source);
|
||||
const targetGenericRestType = sourceGenericRestType ? getGenericRestType(target) : undefined;
|
||||
if (sourceGenericRestType && !(targetGenericRestType && sourceCount === targetCount)) {
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
@@ -10524,8 +10524,8 @@ namespace ts {
|
||||
const paramCount = Math.max(sourceCount, targetCount);
|
||||
const lastIndex = paramCount - 1;
|
||||
for (let i = 0; i < paramCount; i++) {
|
||||
const sourceType = i === lastIndex && sourceRestTypeParameter || getTypeAtPosition(source, i);
|
||||
const targetType = i === lastIndex && targetRestTypeParameter || getTypeAtPosition(target, i);
|
||||
const sourceType = i === lastIndex && sourceGenericRestType || getTypeAtPosition(source, i);
|
||||
const targetType = i === lastIndex && targetGenericRestType || getTypeAtPosition(target, i);
|
||||
// In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
|
||||
// how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions,
|
||||
// they naturally relate only contra-variantly). However, if the source and target parameters both have
|
||||
@@ -12800,13 +12800,13 @@ namespace ts {
|
||||
sourceHasRest ? targetCount :
|
||||
targetHasRest ? sourceCount :
|
||||
Math.min(sourceCount, targetCount);
|
||||
const targetRestTypeVariable = getRestTypeParameter(target);
|
||||
const paramCount = targetRestTypeVariable ? Math.min(targetCount - 1, maxCount) : maxCount;
|
||||
const targetGenericRestType = getGenericRestType(target);
|
||||
const paramCount = targetGenericRestType ? Math.min(targetCount - 1, maxCount) : maxCount;
|
||||
for (let i = 0; i < paramCount; i++) {
|
||||
callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i));
|
||||
}
|
||||
if (targetRestTypeVariable) {
|
||||
callback(getRestTypeAtPosition(source, paramCount), targetRestTypeVariable);
|
||||
if (targetGenericRestType) {
|
||||
callback(getRestTypeAtPosition(source, paramCount), targetGenericRestType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18376,8 +18376,8 @@ namespace ts {
|
||||
// We perform two passes over the arguments. In the first pass we infer from all arguments, but use
|
||||
// wildcards for all context sensitive function expressions.
|
||||
const effectiveArgCount = getEffectiveArgumentCount(node, args, signature);
|
||||
const restTypeParameter = getRestTypeParameter(signature);
|
||||
const argCount = restTypeParameter ? Math.min(getParameterCount(signature) - 1, effectiveArgCount) : effectiveArgCount;
|
||||
const genericRestType = getGenericRestType(signature);
|
||||
const argCount = genericRestType ? Math.min(getParameterCount(signature) - 1, effectiveArgCount) : effectiveArgCount;
|
||||
for (let i = 0; i < argCount; i++) {
|
||||
const arg = getEffectiveArgument(node, args, i);
|
||||
// If the effective argument is 'undefined', then it is an argument that is present but is synthetic.
|
||||
@@ -18396,9 +18396,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (restTypeParameter) {
|
||||
const spreadType = getSpreadArgumentType(node, args, argCount, effectiveArgCount, restTypeParameter, context);
|
||||
inferTypes(context.inferences, spreadType, restTypeParameter);
|
||||
if (genericRestType) {
|
||||
const spreadType = getSpreadArgumentType(node, args, argCount, effectiveArgCount, genericRestType, context);
|
||||
inferTypes(context.inferences, spreadType, genericRestType);
|
||||
}
|
||||
|
||||
// In the second pass we visit only context sensitive arguments, and only those that aren't excluded, this
|
||||
@@ -19148,9 +19148,9 @@ namespace ts {
|
||||
}
|
||||
const isJavascript = isInJavaScriptFile(candidate.declaration);
|
||||
candidate = getSignatureInstantiation(candidate, typeArgumentTypes, isJavascript);
|
||||
// If the original signature has a rest type parameter, instantiation may produce a
|
||||
// If the original signature has a generic rest type, instantiation may produce a
|
||||
// signature with different arity and we need to perform another arity check.
|
||||
if (getRestTypeParameter(originalCandidate) && !hasCorrectArity(node, args!, candidate, signatureHelpTrailingComma)) {
|
||||
if (getGenericRestType(originalCandidate) && !hasCorrectArity(node, args!, candidate, signatureHelpTrailingComma)) {
|
||||
candidateForArgumentArityError = candidate;
|
||||
break;
|
||||
}
|
||||
@@ -20080,9 +20080,9 @@ namespace ts {
|
||||
const paramCount = getParameterCount(source);
|
||||
const hasRest = hasEffectiveRestParameter(source);
|
||||
if (hasRest && pos === paramCount - 1) {
|
||||
const restTypeVariable = getRestTypeParameter(source);
|
||||
if (restTypeVariable) {
|
||||
return restTypeVariable;
|
||||
const genericRestType = getGenericRestType(source);
|
||||
if (genericRestType) {
|
||||
return genericRestType;
|
||||
}
|
||||
}
|
||||
const start = hasRest ? Math.min(pos, paramCount - 1) : pos;
|
||||
@@ -20132,11 +20132,11 @@ namespace ts {
|
||||
return signature.minArgumentCount;
|
||||
}
|
||||
|
||||
function getRestTypeParameter(signature: Signature) {
|
||||
function getGenericRestType(signature: Signature) {
|
||||
if (signature.hasRestParameter) {
|
||||
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
|
||||
if (restType.flags & TypeFlags.TypeParameter) {
|
||||
return <TypeParameter>restType;
|
||||
if (restType.flags & TypeFlags.Instantiable) {
|
||||
return restType;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
//// [genericRestTypes.ts]
|
||||
// Repro from #25793
|
||||
|
||||
// Gets the parameters of a function type as a tuple
|
||||
type Parameters<T extends (...args: any[]) => any> = T extends (...args: infer U) => any ? U : never;
|
||||
// Removes the first element from a tuple
|
||||
type Tail<T extends any[]> = ((...args: T) => any) extends ((head: any, ...tail: infer U) => any) ? U : never;
|
||||
|
||||
type MyFunctionType = (foo: number, bar: string) => boolean;
|
||||
|
||||
type Explicit = (...args: Tail<Parameters<MyFunctionType>>) => ReturnType<MyFunctionType>; // (bar: string) => boolean
|
||||
|
||||
type Bind1<T extends (head: any, ...tail: any[]) => any> = (...args: Tail<Parameters<T>>) => ReturnType<T>;
|
||||
type Generic = Bind1<MyFunctionType>; // (bar: string) => boolean
|
||||
|
||||
|
||||
//// [genericRestTypes.js]
|
||||
"use strict";
|
||||
// Repro from #25793
|
||||
@@ -0,0 +1,55 @@
|
||||
=== tests/cases/compiler/genericRestTypes.ts ===
|
||||
// Repro from #25793
|
||||
|
||||
// Gets the parameters of a function type as a tuple
|
||||
type Parameters<T extends (...args: any[]) => any> = T extends (...args: infer U) => any ? U : never;
|
||||
>Parameters : Symbol(Parameters, Decl(genericRestTypes.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(genericRestTypes.ts, 3, 16))
|
||||
>args : Symbol(args, Decl(genericRestTypes.ts, 3, 27))
|
||||
>T : Symbol(T, Decl(genericRestTypes.ts, 3, 16))
|
||||
>args : Symbol(args, Decl(genericRestTypes.ts, 3, 64))
|
||||
>U : Symbol(U, Decl(genericRestTypes.ts, 3, 78))
|
||||
>U : Symbol(U, Decl(genericRestTypes.ts, 3, 78))
|
||||
|
||||
// Removes the first element from a tuple
|
||||
type Tail<T extends any[]> = ((...args: T) => any) extends ((head: any, ...tail: infer U) => any) ? U : never;
|
||||
>Tail : Symbol(Tail, Decl(genericRestTypes.ts, 3, 101))
|
||||
>T : Symbol(T, Decl(genericRestTypes.ts, 5, 10))
|
||||
>args : Symbol(args, Decl(genericRestTypes.ts, 5, 31))
|
||||
>T : Symbol(T, Decl(genericRestTypes.ts, 5, 10))
|
||||
>head : Symbol(head, Decl(genericRestTypes.ts, 5, 61))
|
||||
>tail : Symbol(tail, Decl(genericRestTypes.ts, 5, 71))
|
||||
>U : Symbol(U, Decl(genericRestTypes.ts, 5, 86))
|
||||
>U : Symbol(U, Decl(genericRestTypes.ts, 5, 86))
|
||||
|
||||
type MyFunctionType = (foo: number, bar: string) => boolean;
|
||||
>MyFunctionType : Symbol(MyFunctionType, Decl(genericRestTypes.ts, 5, 110))
|
||||
>foo : Symbol(foo, Decl(genericRestTypes.ts, 7, 23))
|
||||
>bar : Symbol(bar, Decl(genericRestTypes.ts, 7, 35))
|
||||
|
||||
type Explicit = (...args: Tail<Parameters<MyFunctionType>>) => ReturnType<MyFunctionType>; // (bar: string) => boolean
|
||||
>Explicit : Symbol(Explicit, Decl(genericRestTypes.ts, 7, 60))
|
||||
>args : Symbol(args, Decl(genericRestTypes.ts, 9, 17))
|
||||
>Tail : Symbol(Tail, Decl(genericRestTypes.ts, 3, 101))
|
||||
>Parameters : Symbol(Parameters, Decl(genericRestTypes.ts, 0, 0))
|
||||
>MyFunctionType : Symbol(MyFunctionType, Decl(genericRestTypes.ts, 5, 110))
|
||||
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
|
||||
>MyFunctionType : Symbol(MyFunctionType, Decl(genericRestTypes.ts, 5, 110))
|
||||
|
||||
type Bind1<T extends (head: any, ...tail: any[]) => any> = (...args: Tail<Parameters<T>>) => ReturnType<T>;
|
||||
>Bind1 : Symbol(Bind1, Decl(genericRestTypes.ts, 9, 90))
|
||||
>T : Symbol(T, Decl(genericRestTypes.ts, 11, 11))
|
||||
>head : Symbol(head, Decl(genericRestTypes.ts, 11, 22))
|
||||
>tail : Symbol(tail, Decl(genericRestTypes.ts, 11, 32))
|
||||
>args : Symbol(args, Decl(genericRestTypes.ts, 11, 60))
|
||||
>Tail : Symbol(Tail, Decl(genericRestTypes.ts, 3, 101))
|
||||
>Parameters : Symbol(Parameters, Decl(genericRestTypes.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(genericRestTypes.ts, 11, 11))
|
||||
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(genericRestTypes.ts, 11, 11))
|
||||
|
||||
type Generic = Bind1<MyFunctionType>; // (bar: string) => boolean
|
||||
>Generic : Symbol(Generic, Decl(genericRestTypes.ts, 11, 107))
|
||||
>Bind1 : Symbol(Bind1, Decl(genericRestTypes.ts, 9, 90))
|
||||
>MyFunctionType : Symbol(MyFunctionType, Decl(genericRestTypes.ts, 5, 110))
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
=== tests/cases/compiler/genericRestTypes.ts ===
|
||||
// Repro from #25793
|
||||
|
||||
// Gets the parameters of a function type as a tuple
|
||||
type Parameters<T extends (...args: any[]) => any> = T extends (...args: infer U) => any ? U : never;
|
||||
>Parameters : Parameters<T>
|
||||
>T : T
|
||||
>args : any[]
|
||||
>T : T
|
||||
>args : U
|
||||
>U : U
|
||||
>U : U
|
||||
|
||||
// Removes the first element from a tuple
|
||||
type Tail<T extends any[]> = ((...args: T) => any) extends ((head: any, ...tail: infer U) => any) ? U : never;
|
||||
>Tail : Tail<T>
|
||||
>T : T
|
||||
>args : T
|
||||
>T : T
|
||||
>head : any
|
||||
>tail : U
|
||||
>U : U
|
||||
>U : U
|
||||
|
||||
type MyFunctionType = (foo: number, bar: string) => boolean;
|
||||
>MyFunctionType : MyFunctionType
|
||||
>foo : number
|
||||
>bar : string
|
||||
|
||||
type Explicit = (...args: Tail<Parameters<MyFunctionType>>) => ReturnType<MyFunctionType>; // (bar: string) => boolean
|
||||
>Explicit : Explicit
|
||||
>args : [string]
|
||||
>Tail : Tail<T>
|
||||
>Parameters : Parameters<T>
|
||||
>MyFunctionType : MyFunctionType
|
||||
>ReturnType : ReturnType<T>
|
||||
>MyFunctionType : MyFunctionType
|
||||
|
||||
type Bind1<T extends (head: any, ...tail: any[]) => any> = (...args: Tail<Parameters<T>>) => ReturnType<T>;
|
||||
>Bind1 : Bind1<T>
|
||||
>T : T
|
||||
>head : any
|
||||
>tail : any[]
|
||||
>args : Tail<Parameters<T>>
|
||||
>Tail : Tail<T>
|
||||
>Parameters : Parameters<T>
|
||||
>T : T
|
||||
>ReturnType : ReturnType<T>
|
||||
>T : T
|
||||
|
||||
type Generic = Bind1<MyFunctionType>; // (bar: string) => boolean
|
||||
>Generic : Bind1<MyFunctionType>
|
||||
>Bind1 : Bind1<T>
|
||||
>MyFunctionType : MyFunctionType
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// @strict: true
|
||||
|
||||
// Repro from #25793
|
||||
|
||||
// Gets the parameters of a function type as a tuple
|
||||
type Parameters<T extends (...args: any[]) => any> = T extends (...args: infer U) => any ? U : never;
|
||||
// Removes the first element from a tuple
|
||||
type Tail<T extends any[]> = ((...args: T) => any) extends ((head: any, ...tail: infer U) => any) ? U : never;
|
||||
|
||||
type MyFunctionType = (foo: number, bar: string) => boolean;
|
||||
|
||||
type Explicit = (...args: Tail<Parameters<MyFunctionType>>) => ReturnType<MyFunctionType>; // (bar: string) => boolean
|
||||
|
||||
type Bind1<T extends (head: any, ...tail: any[]) => any> = (...args: Tail<Parameters<T>>) => ReturnType<T>;
|
||||
type Generic = Bind1<MyFunctionType>; // (bar: string) => boolean
|
||||
Reference in New Issue
Block a user