mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-10 17:05:58 -05:00
Support variadic tuple inference from trailing optional to non-optional (#39614)
* Permit variadic tuple inference from trailing optional to non-optional * Add tests
This commit is contained in:
@@ -18501,8 +18501,8 @@ namespace ts {
|
||||
return restType && createArrayType(restType);
|
||||
}
|
||||
|
||||
function getEndLengthOfType(type: Type) {
|
||||
return isTupleType(type) ? getTypeReferenceArity(type) - findLastIndex(type.target.elementFlags, f => !(f & ElementFlags.Required)) - 1 : 0;
|
||||
function getEndLengthOfType(type: Type, flags: ElementFlags) {
|
||||
return isTupleType(type) ? getTypeReferenceArity(type) - findLastIndex(type.target.elementFlags, f => !(f & flags)) - 1 : 0;
|
||||
}
|
||||
|
||||
function getElementTypeOfSliceOfTupleType(type: TupleTypeReference, index: number, endSkipCount = 0, writing = false) {
|
||||
@@ -19763,8 +19763,8 @@ namespace ts {
|
||||
const sourceRestType = !isTupleType(source) || sourceArity > 0 && source.target.elementFlags[sourceArity - 1] & ElementFlags.Rest ?
|
||||
getTypeArguments(source)[sourceArity - 1] : undefined;
|
||||
const endLength = !(target.target.combinedFlags & ElementFlags.Variable) ? 0 :
|
||||
sourceRestType ? getEndLengthOfType(target) :
|
||||
Math.min(getEndLengthOfType(source), getEndLengthOfType(target));
|
||||
sourceRestType ? getEndLengthOfType(target, ElementFlags.Required) :
|
||||
Math.min(getEndLengthOfType(source, ElementFlags.Required | ElementFlags.Optional), getEndLengthOfType(target, ElementFlags.Required));
|
||||
const sourceEndLength = sourceRestType ? 0 : endLength;
|
||||
// Infer between starting fixed elements.
|
||||
for (let i = 0; i < startLength; i++) {
|
||||
|
||||
@@ -473,4 +473,17 @@ tests/cases/conformance/types/tuple/variadicTuples1.ts(342,19): error TS2322: Ty
|
||||
|
||||
declare const a: Desc<[string, number, boolean], object>;
|
||||
const b = a.bind("", 1); // Desc<[boolean], object>
|
||||
|
||||
// Repro from #39607
|
||||
|
||||
declare function getUser(id: string, options?: { x?: string }): string;
|
||||
|
||||
declare function getOrgUser(id: string, orgId: number, options?: { y?: number, z?: boolean }): void;
|
||||
|
||||
function callApi<T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) {
|
||||
return (...args: [...T]) => method(...args, {});
|
||||
}
|
||||
|
||||
callApi(getUser);
|
||||
callApi(getOrgUser);
|
||||
|
||||
@@ -361,6 +361,19 @@ interface Desc<A extends unknown[], T> {
|
||||
|
||||
declare const a: Desc<[string, number, boolean], object>;
|
||||
const b = a.bind("", 1); // Desc<[boolean], object>
|
||||
|
||||
// Repro from #39607
|
||||
|
||||
declare function getUser(id: string, options?: { x?: string }): string;
|
||||
|
||||
declare function getOrgUser(id: string, orgId: number, options?: { y?: number, z?: boolean }): void;
|
||||
|
||||
function callApi<T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) {
|
||||
return (...args: [...T]) => method(...args, {});
|
||||
}
|
||||
|
||||
callApi(getUser);
|
||||
callApi(getOrgUser);
|
||||
|
||||
|
||||
//// [variadicTuples1.js]
|
||||
@@ -568,6 +581,17 @@ function f23(args) {
|
||||
var v3 = f22(["foo", 42]); // [string]
|
||||
}
|
||||
var b = a.bind("", 1); // Desc<[boolean], object>
|
||||
function callApi(method) {
|
||||
return function () {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
return method.apply(void 0, __spreadArrays(args, [{}]));
|
||||
};
|
||||
}
|
||||
callApi(getUser);
|
||||
callApi(getOrgUser);
|
||||
|
||||
|
||||
//// [variadicTuples1.d.ts]
|
||||
@@ -720,3 +744,11 @@ interface Desc<A extends unknown[], T> {
|
||||
}
|
||||
declare const a: Desc<[string, number, boolean], object>;
|
||||
declare const b: Desc<[boolean], object>;
|
||||
declare function getUser(id: string, options?: {
|
||||
x?: string;
|
||||
}): string;
|
||||
declare function getOrgUser(id: string, orgId: number, options?: {
|
||||
y?: number;
|
||||
z?: boolean;
|
||||
}): void;
|
||||
declare function callApi<T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U): (...args_0: T) => U;
|
||||
|
||||
@@ -1244,3 +1244,43 @@ const b = a.bind("", 1); // Desc<[boolean], object>
|
||||
>a : Symbol(a, Decl(variadicTuples1.ts, 360, 13))
|
||||
>bind : Symbol(Desc.bind, Decl(variadicTuples1.ts, 356, 34))
|
||||
|
||||
// Repro from #39607
|
||||
|
||||
declare function getUser(id: string, options?: { x?: string }): string;
|
||||
>getUser : Symbol(getUser, Decl(variadicTuples1.ts, 361, 24))
|
||||
>id : Symbol(id, Decl(variadicTuples1.ts, 365, 25))
|
||||
>options : Symbol(options, Decl(variadicTuples1.ts, 365, 36))
|
||||
>x : Symbol(x, Decl(variadicTuples1.ts, 365, 48))
|
||||
|
||||
declare function getOrgUser(id: string, orgId: number, options?: { y?: number, z?: boolean }): void;
|
||||
>getOrgUser : Symbol(getOrgUser, Decl(variadicTuples1.ts, 365, 71))
|
||||
>id : Symbol(id, Decl(variadicTuples1.ts, 367, 28))
|
||||
>orgId : Symbol(orgId, Decl(variadicTuples1.ts, 367, 39))
|
||||
>options : Symbol(options, Decl(variadicTuples1.ts, 367, 54))
|
||||
>y : Symbol(y, Decl(variadicTuples1.ts, 367, 66))
|
||||
>z : Symbol(z, Decl(variadicTuples1.ts, 367, 78))
|
||||
|
||||
function callApi<T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) {
|
||||
>callApi : Symbol(callApi, Decl(variadicTuples1.ts, 367, 100))
|
||||
>T : Symbol(T, Decl(variadicTuples1.ts, 369, 17))
|
||||
>U : Symbol(U, Decl(variadicTuples1.ts, 369, 42))
|
||||
>method : Symbol(method, Decl(variadicTuples1.ts, 369, 53))
|
||||
>args : Symbol(args, Decl(variadicTuples1.ts, 369, 62))
|
||||
>T : Symbol(T, Decl(variadicTuples1.ts, 369, 17))
|
||||
>U : Symbol(U, Decl(variadicTuples1.ts, 369, 42))
|
||||
|
||||
return (...args: [...T]) => method(...args, {});
|
||||
>args : Symbol(args, Decl(variadicTuples1.ts, 370, 12))
|
||||
>T : Symbol(T, Decl(variadicTuples1.ts, 369, 17))
|
||||
>method : Symbol(method, Decl(variadicTuples1.ts, 369, 53))
|
||||
>args : Symbol(args, Decl(variadicTuples1.ts, 370, 12))
|
||||
}
|
||||
|
||||
callApi(getUser);
|
||||
>callApi : Symbol(callApi, Decl(variadicTuples1.ts, 367, 100))
|
||||
>getUser : Symbol(getUser, Decl(variadicTuples1.ts, 361, 24))
|
||||
|
||||
callApi(getOrgUser);
|
||||
>callApi : Symbol(callApi, Decl(variadicTuples1.ts, 367, 100))
|
||||
>getOrgUser : Symbol(getOrgUser, Decl(variadicTuples1.ts, 365, 71))
|
||||
|
||||
|
||||
@@ -1279,3 +1279,44 @@ const b = a.bind("", 1); // Desc<[boolean], object>
|
||||
>"" : ""
|
||||
>1 : 1
|
||||
|
||||
// Repro from #39607
|
||||
|
||||
declare function getUser(id: string, options?: { x?: string }): string;
|
||||
>getUser : (id: string, options?: { x?: string | undefined; } | undefined) => string
|
||||
>id : string
|
||||
>options : { x?: string | undefined; } | undefined
|
||||
>x : string | undefined
|
||||
|
||||
declare function getOrgUser(id: string, orgId: number, options?: { y?: number, z?: boolean }): void;
|
||||
>getOrgUser : (id: string, orgId: number, options?: { y?: number | undefined; z?: boolean | undefined; } | undefined) => void
|
||||
>id : string
|
||||
>orgId : number
|
||||
>options : { y?: number | undefined; z?: boolean | undefined; } | undefined
|
||||
>y : number | undefined
|
||||
>z : boolean | undefined
|
||||
|
||||
function callApi<T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) {
|
||||
>callApi : <T extends unknown[] = [], U = void>(method: (...args_0: T, args_1: object) => U) => (...args_0: T) => U
|
||||
>method : (...args_0: T, args_1: object) => U
|
||||
>args : [...T, object]
|
||||
|
||||
return (...args: [...T]) => method(...args, {});
|
||||
>(...args: [...T]) => method(...args, {}) : (...args_0: T) => U
|
||||
>args : [...T]
|
||||
>method(...args, {}) : U
|
||||
>method : (...args_0: T, args_1: object) => U
|
||||
>...args : T[number]
|
||||
>args : [...T]
|
||||
>{} : {}
|
||||
}
|
||||
|
||||
callApi(getUser);
|
||||
>callApi(getUser) : (id: string) => string
|
||||
>callApi : <T extends unknown[] = [], U = void>(method: (...args_0: T, args_1: object) => U) => (...args_0: T) => U
|
||||
>getUser : (id: string, options?: { x?: string | undefined; } | undefined) => string
|
||||
|
||||
callApi(getOrgUser);
|
||||
>callApi(getOrgUser) : (id: string, orgId: number) => void
|
||||
>callApi : <T extends unknown[] = [], U = void>(method: (...args_0: T, args_1: object) => U) => (...args_0: T) => U
|
||||
>getOrgUser : (id: string, orgId: number, options?: { y?: number | undefined; z?: boolean | undefined; } | undefined) => void
|
||||
|
||||
|
||||
@@ -363,3 +363,16 @@ interface Desc<A extends unknown[], T> {
|
||||
|
||||
declare const a: Desc<[string, number, boolean], object>;
|
||||
const b = a.bind("", 1); // Desc<[boolean], object>
|
||||
|
||||
// Repro from #39607
|
||||
|
||||
declare function getUser(id: string, options?: { x?: string }): string;
|
||||
|
||||
declare function getOrgUser(id: string, orgId: number, options?: { y?: number, z?: boolean }): void;
|
||||
|
||||
function callApi<T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) {
|
||||
return (...args: [...T]) => method(...args, {});
|
||||
}
|
||||
|
||||
callApi(getUser);
|
||||
callApi(getOrgUser);
|
||||
|
||||
Reference in New Issue
Block a user