mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Allowed tuples to have both named and anonymous members (#53356)
Co-authored-by: Jake Bailey <jabaile@microsoft.com> Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com> Co-authored-by: Daniel Rosenwasser <drosenwasser@microsoft.com>
This commit is contained in:
co-authored by
Jake Bailey
Mateusz Burzyński
Daniel Rosenwasser
parent
a94eb319eb
commit
5b85e9469a
+37
-37
@@ -6888,21 +6888,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const arity = getTypeReferenceArity(type);
|
||||
const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context);
|
||||
if (tupleConstituentNodes) {
|
||||
if ((type.target as TupleType).labeledElementDeclarations) {
|
||||
for (let i = 0; i < tupleConstituentNodes.length; i++) {
|
||||
const flags = (type.target as TupleType).elementFlags[i];
|
||||
const { labeledElementDeclarations } = type.target as TupleType;
|
||||
for (let i = 0; i < tupleConstituentNodes.length; i++) {
|
||||
const flags = (type.target as TupleType).elementFlags[i];
|
||||
const labeledElementDeclaration = labeledElementDeclarations?.[i];
|
||||
|
||||
if (labeledElementDeclaration) {
|
||||
tupleConstituentNodes[i] = factory.createNamedTupleMember(
|
||||
flags & ElementFlags.Variable ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined,
|
||||
factory.createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel((type.target as TupleType).labeledElementDeclarations![i]))),
|
||||
factory.createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel(labeledElementDeclaration))),
|
||||
flags & ElementFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
|
||||
flags & ElementFlags.Rest ? factory.createArrayTypeNode(tupleConstituentNodes[i]) :
|
||||
tupleConstituentNodes[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < Math.min(arity, tupleConstituentNodes.length); i++) {
|
||||
const flags = (type.target as TupleType).elementFlags[i];
|
||||
else {
|
||||
tupleConstituentNodes[i] =
|
||||
flags & ElementFlags.Variable ? factory.createRestTypeNode(flags & ElementFlags.Rest ? factory.createArrayTypeNode(tupleConstituentNodes[i]) : tupleConstituentNodes[i]) :
|
||||
flags & ElementFlags.Optional ? factory.createOptionalTypeNode(tupleConstituentNodes[i]) :
|
||||
@@ -12657,19 +12657,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
function getExpandedParameters(sig: Signature, skipUnionExpanding?: boolean): readonly (readonly Symbol[])[] {
|
||||
if (signatureHasRestParameter(sig)) {
|
||||
const restIndex = sig.parameters.length - 1;
|
||||
const restName = sig.parameters[restIndex].escapedName;
|
||||
const restType = getTypeOfSymbol(sig.parameters[restIndex]);
|
||||
if (isTupleType(restType)) {
|
||||
return [expandSignatureParametersWithTupleMembers(restType, restIndex)];
|
||||
return [expandSignatureParametersWithTupleMembers(restType, restIndex, restName)];
|
||||
}
|
||||
else if (!skipUnionExpanding && restType.flags & TypeFlags.Union && every((restType as UnionType).types, isTupleType)) {
|
||||
return map((restType as UnionType).types, t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex));
|
||||
return map((restType as UnionType).types, t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex, restName));
|
||||
}
|
||||
}
|
||||
return [sig.parameters];
|
||||
|
||||
function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number) {
|
||||
const elementTypes = getElementTypes(restType);
|
||||
const associatedNames = getUniqAssociatedNamesFromTupleType(restType);
|
||||
function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number, restName: __String) {
|
||||
const elementTypes = getTypeArguments(restType);
|
||||
const associatedNames = getUniqAssociatedNamesFromTupleType(restType, restName);
|
||||
const restParams = map(elementTypes, (t, i) => {
|
||||
// Lookup the label from the individual tuple passed in before falling back to the signature `rest` parameter name
|
||||
const name = associatedNames && associatedNames[i] ? associatedNames[i] :
|
||||
@@ -12684,10 +12685,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return concatenate(sig.parameters.slice(0, restIndex), restParams);
|
||||
}
|
||||
|
||||
function getUniqAssociatedNamesFromTupleType(type: TupleTypeReference) {
|
||||
function getUniqAssociatedNamesFromTupleType(type: TupleTypeReference, restName: __String) {
|
||||
const associatedNamesMap = new Map<__String, number>();
|
||||
return map(type.target.labeledElementDeclarations, labeledElement => {
|
||||
const name = getTupleElementLabel(labeledElement);
|
||||
return map(type.target.labeledElementDeclarations, (labeledElement, i) => {
|
||||
const name = getTupleElementLabel(labeledElement, i, restName);
|
||||
const prevCounter = associatedNamesMap.get(name);
|
||||
if (prevCounter === undefined) {
|
||||
associatedNamesMap.set(name, 1);
|
||||
@@ -15963,8 +15964,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return readonly ? globalReadonlyArrayType : globalArrayType;
|
||||
}
|
||||
const elementFlags = map((node as TupleTypeNode).elements, getTupleElementFlags);
|
||||
const missingName = some((node as TupleTypeNode).elements, e => e.kind !== SyntaxKind.NamedTupleMember);
|
||||
return getTupleTargetType(elementFlags, readonly, /*associatedNames*/ missingName ? undefined : (node as TupleTypeNode).elements as readonly NamedTupleMember[]);
|
||||
return getTupleTargetType(elementFlags, readonly, map((node as TupleTypeNode).elements, memberIfLabeledElementDeclaration));
|
||||
}
|
||||
|
||||
function memberIfLabeledElementDeclaration(member: Node): NamedTupleMember | ParameterDeclaration | undefined {
|
||||
return isNamedTupleMember(member) || isParameter(member) ? member : undefined;
|
||||
}
|
||||
|
||||
// Return true if the given type reference node is directly aliased or if it needs to be deferred
|
||||
@@ -16054,21 +16058,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return isTypeOperatorNode(node) && node.operator === SyntaxKind.ReadonlyKeyword;
|
||||
}
|
||||
|
||||
function createTupleType(elementTypes: readonly Type[], elementFlags?: readonly ElementFlags[], readonly = false, namedMemberDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[]) {
|
||||
function createTupleType(elementTypes: readonly Type[], elementFlags?: readonly ElementFlags[], readonly = false, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined)[] = []) {
|
||||
const tupleTarget = getTupleTargetType(elementFlags || map(elementTypes, _ => ElementFlags.Required), readonly, namedMemberDeclarations);
|
||||
return tupleTarget === emptyGenericType ? emptyObjectType :
|
||||
elementTypes.length ? createNormalizedTypeReference(tupleTarget, elementTypes) :
|
||||
tupleTarget;
|
||||
}
|
||||
|
||||
function getTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[]): GenericType {
|
||||
function getTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined)[]): GenericType {
|
||||
if (elementFlags.length === 1 && elementFlags[0] & ElementFlags.Rest) {
|
||||
// [...X[]] is equivalent to just X[]
|
||||
return readonly ? globalReadonlyArrayType : globalArrayType;
|
||||
}
|
||||
const memberIds = mapDefined(namedMemberDeclarations, node => node ? getNodeId(node) : undefined);
|
||||
const key = map(elementFlags, f => f & ElementFlags.Required ? "#" : f & ElementFlags.Optional ? "?" : f & ElementFlags.Rest ? "." : "*").join() +
|
||||
(readonly ? "R" : "") +
|
||||
(namedMemberDeclarations && namedMemberDeclarations.length ? "," + map(namedMemberDeclarations, getNodeId).join(",") : "");
|
||||
(memberIds.length ? "," + memberIds.join(",") : "");
|
||||
let type = tupleTypes.get(key);
|
||||
if (!type) {
|
||||
tupleTypes.set(key, type = createTupleTargetType(elementFlags, readonly, namedMemberDeclarations));
|
||||
@@ -16083,7 +16088,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
//
|
||||
// Note that the generic type created by this function has no symbol associated with it. The same
|
||||
// is true for each of the synthesized type parameters.
|
||||
function createTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration)[] | undefined): TupleType {
|
||||
function createTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined)[]): TupleType {
|
||||
const arity = elementFlags.length;
|
||||
const minLength = countWhere(elementFlags, f => !!(f & (ElementFlags.Required | ElementFlags.Variadic)));
|
||||
let typeParameters: TypeParameter[] | undefined;
|
||||
@@ -16165,7 +16170,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// In either layout, zero or more generic variadic elements may be present at any location.
|
||||
const expandedTypes: Type[] = [];
|
||||
const expandedFlags: ElementFlags[] = [];
|
||||
let expandedDeclarations: (NamedTupleMember | ParameterDeclaration)[] | undefined = [];
|
||||
const expandedDeclarations: (NamedTupleMember | ParameterDeclaration | undefined)[] = [];
|
||||
let lastRequiredIndex = -1;
|
||||
let firstRestIndex = -1;
|
||||
let lastOptionalOrRestIndex = -1;
|
||||
@@ -16208,7 +16213,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
(t, i) => expandedFlags[firstRestIndex + i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t));
|
||||
expandedTypes.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex);
|
||||
expandedFlags.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex);
|
||||
expandedDeclarations?.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex);
|
||||
expandedDeclarations.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex);
|
||||
}
|
||||
const tupleTarget = getTupleTargetType(expandedFlags, target.readonly, expandedDeclarations);
|
||||
return tupleTarget === emptyGenericType ? emptyObjectType :
|
||||
@@ -16227,12 +16232,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
expandedTypes.push(flags & ElementFlags.Optional ? addOptionality(type, /*isProperty*/ true) : type);
|
||||
expandedFlags.push(flags);
|
||||
if (expandedDeclarations && declaration) {
|
||||
expandedDeclarations.push(declaration);
|
||||
}
|
||||
else {
|
||||
expandedDeclarations = undefined;
|
||||
}
|
||||
expandedDeclarations.push(declaration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34828,7 +34828,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return type;
|
||||
}
|
||||
|
||||
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember) {
|
||||
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember): __String;
|
||||
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index: number, restParameterName?: __String): __String;
|
||||
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index?: number, restParameterName = "arg" as __String) {
|
||||
if (!d) {
|
||||
return `${restParameterName}_${index}` as __String;
|
||||
}
|
||||
Debug.assert(isIdentifier(d.name)); // Parameter declarations could be binding patterns, but we only allow identifier names
|
||||
return d.name.escapedText;
|
||||
}
|
||||
@@ -34843,7 +34848,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (isTupleType(restType)) {
|
||||
const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations;
|
||||
const index = pos - paramCount;
|
||||
return associatedNames && getTupleElementLabel(associatedNames[index]) || restParameter.escapedName + "_" + index as __String;
|
||||
return getTupleElementLabel(associatedNames?.[index], index, restParameter.escapedName);
|
||||
}
|
||||
return restParameter.escapedName;
|
||||
}
|
||||
@@ -38870,12 +38875,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const elementTypes = node.elements;
|
||||
let seenOptionalElement = false;
|
||||
let seenRestElement = false;
|
||||
const hasNamedElement = some(elementTypes, isNamedTupleMember);
|
||||
for (const e of elementTypes) {
|
||||
if (e.kind !== SyntaxKind.NamedTupleMember && hasNamedElement) {
|
||||
grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names);
|
||||
break;
|
||||
}
|
||||
const flags = getTupleElementFlags(e);
|
||||
if (flags & ElementFlags.Variadic) {
|
||||
const type = getTypeFromTypeNode((e as RestTypeNode | NamedTupleMember).type);
|
||||
|
||||
@@ -4277,10 +4277,6 @@
|
||||
"category": "Error",
|
||||
"code": 5083
|
||||
},
|
||||
"Tuple members must all have names or all not have names.": {
|
||||
"category": "Error",
|
||||
"code": 5084
|
||||
},
|
||||
"A tuple member cannot be both optional and rest.": {
|
||||
"category": "Error",
|
||||
"code": 5085
|
||||
|
||||
@@ -6434,7 +6434,7 @@ export interface TupleType extends GenericType {
|
||||
hasRestElement: boolean;
|
||||
combinedFlags: ElementFlags;
|
||||
readonly: boolean;
|
||||
labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[];
|
||||
labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration | undefined)[];
|
||||
}
|
||||
|
||||
export interface TupleTypeReference extends TypeReference {
|
||||
|
||||
+1
-1
@@ -6951,7 +6951,7 @@ declare namespace ts {
|
||||
hasRestElement: boolean;
|
||||
combinedFlags: ElementFlags;
|
||||
readonly: boolean;
|
||||
labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[];
|
||||
labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration | undefined)[];
|
||||
}
|
||||
interface TupleTypeReference extends TypeReference {
|
||||
target: TupleType;
|
||||
|
||||
+1
-1
@@ -2898,7 +2898,7 @@ declare namespace ts {
|
||||
hasRestElement: boolean;
|
||||
combinedFlags: ElementFlags;
|
||||
readonly: boolean;
|
||||
labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[];
|
||||
labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration | undefined)[];
|
||||
}
|
||||
interface TupleTypeReference extends TypeReference {
|
||||
target: TupleType;
|
||||
|
||||
@@ -444,7 +444,7 @@ type T05<T extends any[]> = Parameters<(x: string, ...args: T) => void>;
|
||||
>args : T
|
||||
|
||||
type T06 = T05<[number, ...boolean[]]>;
|
||||
>T06 : [string, number, ...boolean[]]
|
||||
>T06 : [x: string, number, ...boolean[]]
|
||||
|
||||
type P1<T extends Function> = T extends (head: infer A, ...tail: infer B) => any ? { head: A, tail: B } : any[];
|
||||
>P1 : P1<T>
|
||||
|
||||
@@ -264,19 +264,19 @@ ff2 = ff1;
|
||||
function ff3<A extends unknown[]>(s1: (...args: [x: string, ...rest: A | [number]]) => void, s2: (x: string, ...rest: A | [number]) => void) {
|
||||
>ff3 : <A extends unknown[]>(s1: (...args: [x: string, ...rest: A | [number]]) => void, s2: (x: string, ...rest: A | [number]) => void) => void
|
||||
>s1 : (...args: [x: string, ...rest: A | [number]]) => void
|
||||
>args : [string, number] | [x: string, ...rest: A]
|
||||
>args : [x: string, number] | [x: string, ...rest: A]
|
||||
>s2 : (x: string, ...rest: A | [number]) => void
|
||||
>x : string
|
||||
>rest : [number] | A
|
||||
|
||||
s1 = s2;
|
||||
>s1 = s2 : (x: string, ...rest: [number] | A) => void
|
||||
>s1 : (...args: [string, number] | [x: string, ...rest: A]) => void
|
||||
>s1 : (...args: [x: string, number] | [x: string, ...rest: A]) => void
|
||||
>s2 : (x: string, ...rest: [number] | A) => void
|
||||
|
||||
s2 = s1;
|
||||
>s2 = s1 : (...args: [string, number] | [x: string, ...rest: A]) => void
|
||||
>s2 = s1 : (...args: [x: string, number] | [x: string, ...rest: A]) => void
|
||||
>s2 : (x: string, ...rest: [number] | A) => void
|
||||
>s1 : (...args: [string, number] | [x: string, ...rest: A]) => void
|
||||
>s1 : (...args: [x: string, number] | [x: string, ...rest: A]) => void
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ type SubTup2VariadicAndRest<T extends unknown[]> = T extends [
|
||||
: never;
|
||||
|
||||
type SubTup2VariadicAndRestTest = SubTup2VariadicAndRest<[a: 0, b: 1, ...c: 2[]]>;
|
||||
>SubTup2VariadicAndRestTest : [0, 1, 2]
|
||||
>SubTup2VariadicAndRestTest : [a: 0, b: 1, 2]
|
||||
|
||||
type SubTup2TrailingVariadic<T extends unknown[]> = T extends [
|
||||
>SubTup2TrailingVariadic : SubTup2TrailingVariadic<T>
|
||||
@@ -67,7 +67,7 @@ type SubTup2RestAndTrailingVariadic2<T extends unknown[]> = T extends [
|
||||
: never;
|
||||
|
||||
type SubTup2RestAndTrailingVariadic2Test = SubTup2RestAndTrailingVariadic2<[...a: 0[], b: 1, c: 2]>;
|
||||
>SubTup2RestAndTrailingVariadic2Test : [0, 1, 2]
|
||||
>SubTup2RestAndTrailingVariadic2Test : [0, b: 1, c: 2]
|
||||
|
||||
type SubTup2VariadicWithLeadingFixedElements<T extends unknown[]> = T extends [
|
||||
>SubTup2VariadicWithLeadingFixedElements : SubTup2VariadicWithLeadingFixedElements<T>
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
namedTupleMembersErrors.ts(1,41): error TS5084: Tuple members must all have names or all not have names.
|
||||
namedTupleMembersErrors.ts(2,25): error TS5084: Tuple members must all have names or all not have names.
|
||||
namedTupleMembersErrors.ts(4,32): error TS5084: Tuple members must all have names or all not have names.
|
||||
namedTupleMembersErrors.ts(5,22): error TS5084: Tuple members must all have names or all not have names.
|
||||
namedTupleMembersErrors.ts(7,32): error TS5084: Tuple members must all have names or all not have names.
|
||||
namedTupleMembersErrors.ts(8,22): error TS5084: Tuple members must all have names or all not have names.
|
||||
namedTupleMembersErrors.ts(10,29): error TS5086: A labeled tuple element is declared as optional with a question mark after the name and before the colon, rather than after the type.
|
||||
namedTupleMembersErrors.ts(12,46): error TS5087: A labeled tuple element is declared as rest with a '...' before the name, rather than before the type.
|
||||
namedTupleMembersErrors.ts(14,49): error TS5087: A labeled tuple element is declared as rest with a '...' before the name, rather than before the type.
|
||||
@@ -14,27 +8,15 @@ namedTupleMembersErrors.ts(20,13): error TS2456: Type alias 'RecusiveRestUnlabel
|
||||
namedTupleMembersErrors.ts(21,13): error TS2456: Type alias 'RecusiveRest' circularly references itself.
|
||||
|
||||
|
||||
==== namedTupleMembersErrors.ts (14 errors) ====
|
||||
export type Segment1 = [length: number, number]; // partially named, disallowed
|
||||
~~~~~~
|
||||
!!! error TS5084: Tuple members must all have names or all not have names.
|
||||
export type Segment2 = [number, size: number]; // partially named, disallowed
|
||||
~~~~~~
|
||||
!!! error TS5084: Tuple members must all have names or all not have names.
|
||||
==== namedTupleMembersErrors.ts (8 errors) ====
|
||||
export type Segment1 = [length: number, number];
|
||||
export type Segment2 = [number, size: number];
|
||||
|
||||
export type List = [item: any, ...any]; // partially named, disallowed
|
||||
~~~~~~
|
||||
!!! error TS5084: Tuple members must all have names or all not have names.
|
||||
export type List2 = [any, ...remainder: any]; // partially named, disallowed
|
||||
~~~
|
||||
!!! error TS5084: Tuple members must all have names or all not have names.
|
||||
export type List = [item: any, ...any];
|
||||
export type List2 = [any, ...remainder: any];
|
||||
|
||||
export type Pair = [item: any, any?]; // partially named, disallowed
|
||||
~~~~
|
||||
!!! error TS5084: Tuple members must all have names or all not have names.
|
||||
export type Pair2 = [any, last?: any]; // partially named, disallowed
|
||||
~~~
|
||||
!!! error TS5084: Tuple members must all have names or all not have names.
|
||||
export type Pair = [item: any, any?];
|
||||
export type Pair2 = [any, last?: any];
|
||||
|
||||
export type Opt = [element: string?]; // question mark on element disallowed
|
||||
~~~~~~~
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
//// [tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts] ////
|
||||
|
||||
//// [namedTupleMembersErrors.ts]
|
||||
export type Segment1 = [length: number, number]; // partially named, disallowed
|
||||
export type Segment2 = [number, size: number]; // partially named, disallowed
|
||||
export type Segment1 = [length: number, number];
|
||||
export type Segment2 = [number, size: number];
|
||||
|
||||
export type List = [item: any, ...any]; // partially named, disallowed
|
||||
export type List2 = [any, ...remainder: any]; // partially named, disallowed
|
||||
export type List = [item: any, ...any];
|
||||
export type List2 = [any, ...remainder: any];
|
||||
|
||||
export type Pair = [item: any, any?]; // partially named, disallowed
|
||||
export type Pair2 = [any, last?: any]; // partially named, disallowed
|
||||
export type Pair = [item: any, any?];
|
||||
export type Pair2 = [any, last?: any];
|
||||
|
||||
export type Opt = [element: string?]; // question mark on element disallowed
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
//// [tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts] ////
|
||||
|
||||
=== namedTupleMembersErrors.ts ===
|
||||
export type Segment1 = [length: number, number]; // partially named, disallowed
|
||||
export type Segment1 = [length: number, number];
|
||||
>Segment1 : Symbol(Segment1, Decl(namedTupleMembersErrors.ts, 0, 0))
|
||||
|
||||
export type Segment2 = [number, size: number]; // partially named, disallowed
|
||||
export type Segment2 = [number, size: number];
|
||||
>Segment2 : Symbol(Segment2, Decl(namedTupleMembersErrors.ts, 0, 48))
|
||||
|
||||
export type List = [item: any, ...any]; // partially named, disallowed
|
||||
export type List = [item: any, ...any];
|
||||
>List : Symbol(List, Decl(namedTupleMembersErrors.ts, 1, 46))
|
||||
|
||||
export type List2 = [any, ...remainder: any]; // partially named, disallowed
|
||||
export type List2 = [any, ...remainder: any];
|
||||
>List2 : Symbol(List2, Decl(namedTupleMembersErrors.ts, 3, 39))
|
||||
|
||||
export type Pair = [item: any, any?]; // partially named, disallowed
|
||||
export type Pair = [item: any, any?];
|
||||
>Pair : Symbol(Pair, Decl(namedTupleMembersErrors.ts, 4, 45))
|
||||
|
||||
export type Pair2 = [any, last?: any]; // partially named, disallowed
|
||||
export type Pair2 = [any, last?: any];
|
||||
>Pair2 : Symbol(Pair2, Decl(namedTupleMembersErrors.ts, 6, 37))
|
||||
|
||||
export type Opt = [element: string?]; // question mark on element disallowed
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
//// [tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts] ////
|
||||
|
||||
=== namedTupleMembersErrors.ts ===
|
||||
export type Segment1 = [length: number, number]; // partially named, disallowed
|
||||
>Segment1 : [number, number]
|
||||
export type Segment1 = [length: number, number];
|
||||
>Segment1 : [length: number, number]
|
||||
|
||||
export type Segment2 = [number, size: number]; // partially named, disallowed
|
||||
>Segment2 : [number, number]
|
||||
export type Segment2 = [number, size: number];
|
||||
>Segment2 : [number, size: number]
|
||||
|
||||
export type List = [item: any, ...any]; // partially named, disallowed
|
||||
>List : [any, ...any[]]
|
||||
export type List = [item: any, ...any];
|
||||
>List : [item: any, ...any[]]
|
||||
|
||||
export type List2 = [any, ...remainder: any]; // partially named, disallowed
|
||||
>List2 : [any, ...any[]]
|
||||
export type List2 = [any, ...remainder: any];
|
||||
>List2 : [any, ...remainder: any[]]
|
||||
|
||||
export type Pair = [item: any, any?]; // partially named, disallowed
|
||||
>Pair : [any, any?]
|
||||
export type Pair = [item: any, any?];
|
||||
>Pair : [item: any, any?]
|
||||
|
||||
export type Pair2 = [any, last?: any]; // partially named, disallowed
|
||||
>Pair2 : [any, any?]
|
||||
export type Pair2 = [any, last?: any];
|
||||
>Pair2 : [any, last?: any]
|
||||
|
||||
export type Opt = [element: string?]; // question mark on element disallowed
|
||||
>Opt : [element: string]
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
//// [tests/cases/conformance/types/tuple/named/partiallyNamedTuples.ts] ////
|
||||
|
||||
//// [partiallyNamedTuples.ts]
|
||||
type NamedAndAnonymous = [a: string, number];
|
||||
|
||||
function fa1(...args: NamedAndAnonymous) {}
|
||||
function fa2(a: NamedAndAnonymous, ...args: NamedAndAnonymous) {}
|
||||
|
||||
type NamedAnonymousMixed = [a: string, number, c: number, NamedAndAnonymous];
|
||||
|
||||
function fb1(...args: NamedAnonymousMixed) {}
|
||||
function fb2(a: NamedAnonymousMixed, ...args: NamedAnonymousMixed) {}
|
||||
function fb3(a: NamedAnonymousMixed, ...args: NamedAnonymousMixed[3]) {}
|
||||
|
||||
type ToAnonymousTuple<T extends unknown[]> = {
|
||||
[K in keyof T]: [K, T[K], keyof T, T];
|
||||
};
|
||||
|
||||
type AnonymousToAnonymous = ToAnonymousTuple<[boolean, number]>;
|
||||
type MixedToAnonymous = ToAnonymousTuple<[boolean, second: number]>;
|
||||
type NamedToAnonymous = ToAnonymousTuple<[first: boolean, second: number]>;
|
||||
|
||||
type ToMixedTuple<T extends unknown[]> = {
|
||||
[K in keyof T]: [K, second: T[K], keyof T, fourth: T];
|
||||
};
|
||||
|
||||
type AnonymousToMixed = ToMixedTuple<[boolean, number]>;
|
||||
type MixedToMixed = ToMixedTuple<[boolean, second: number]>;
|
||||
type NamedToMixed = ToMixedTuple<[first: boolean, second: number]>;
|
||||
|
||||
type MixedSpread = [first: boolean, ...[second: string]];
|
||||
|
||||
type ConditionalTuple = [
|
||||
first: boolean,
|
||||
...(0 extends 0 ? [second: string] : [])
|
||||
];
|
||||
|
||||
type AddMixedConditional<T> = [
|
||||
first: boolean,
|
||||
null,
|
||||
third: T extends number ? "a" : "b",
|
||||
...(T extends 0 ? [fourth: "c"] : [])
|
||||
];
|
||||
|
||||
type AddMixedConditionalBoolean = AddMixedConditional<boolean>;
|
||||
type AddMixedConditionalLiteral = AddMixedConditional<0>;
|
||||
type AddMixedConditionalNumberPrimitive = AddMixedConditional<number>;
|
||||
|
||||
declare function test<T extends readonly unknown[]>(
|
||||
arg: [
|
||||
...{
|
||||
[K in keyof T]: {
|
||||
type: T[K];
|
||||
};
|
||||
}
|
||||
]
|
||||
): T;
|
||||
|
||||
declare const input: [first: { type: number }, { type: string }];
|
||||
|
||||
const output = test(input);
|
||||
|
||||
|
||||
//// [partiallyNamedTuples.js]
|
||||
function fa1() {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
}
|
||||
function fa2(a) {
|
||||
var args = [];
|
||||
for (var _i = 1; _i < arguments.length; _i++) {
|
||||
args[_i - 1] = arguments[_i];
|
||||
}
|
||||
}
|
||||
function fb1() {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
}
|
||||
function fb2(a) {
|
||||
var args = [];
|
||||
for (var _i = 1; _i < arguments.length; _i++) {
|
||||
args[_i - 1] = arguments[_i];
|
||||
}
|
||||
}
|
||||
function fb3(a) {
|
||||
var args = [];
|
||||
for (var _i = 1; _i < arguments.length; _i++) {
|
||||
args[_i - 1] = arguments[_i];
|
||||
}
|
||||
}
|
||||
var output = test(input);
|
||||
@@ -0,0 +1,164 @@
|
||||
//// [tests/cases/conformance/types/tuple/named/partiallyNamedTuples.ts] ////
|
||||
|
||||
=== partiallyNamedTuples.ts ===
|
||||
type NamedAndAnonymous = [a: string, number];
|
||||
>NamedAndAnonymous : Symbol(NamedAndAnonymous, Decl(partiallyNamedTuples.ts, 0, 0))
|
||||
|
||||
function fa1(...args: NamedAndAnonymous) {}
|
||||
>fa1 : Symbol(fa1, Decl(partiallyNamedTuples.ts, 0, 45))
|
||||
>args : Symbol(args, Decl(partiallyNamedTuples.ts, 2, 13))
|
||||
>NamedAndAnonymous : Symbol(NamedAndAnonymous, Decl(partiallyNamedTuples.ts, 0, 0))
|
||||
|
||||
function fa2(a: NamedAndAnonymous, ...args: NamedAndAnonymous) {}
|
||||
>fa2 : Symbol(fa2, Decl(partiallyNamedTuples.ts, 2, 43))
|
||||
>a : Symbol(a, Decl(partiallyNamedTuples.ts, 3, 13))
|
||||
>NamedAndAnonymous : Symbol(NamedAndAnonymous, Decl(partiallyNamedTuples.ts, 0, 0))
|
||||
>args : Symbol(args, Decl(partiallyNamedTuples.ts, 3, 34))
|
||||
>NamedAndAnonymous : Symbol(NamedAndAnonymous, Decl(partiallyNamedTuples.ts, 0, 0))
|
||||
|
||||
type NamedAnonymousMixed = [a: string, number, c: number, NamedAndAnonymous];
|
||||
>NamedAnonymousMixed : Symbol(NamedAnonymousMixed, Decl(partiallyNamedTuples.ts, 3, 65))
|
||||
>NamedAndAnonymous : Symbol(NamedAndAnonymous, Decl(partiallyNamedTuples.ts, 0, 0))
|
||||
|
||||
function fb1(...args: NamedAnonymousMixed) {}
|
||||
>fb1 : Symbol(fb1, Decl(partiallyNamedTuples.ts, 5, 77))
|
||||
>args : Symbol(args, Decl(partiallyNamedTuples.ts, 7, 13))
|
||||
>NamedAnonymousMixed : Symbol(NamedAnonymousMixed, Decl(partiallyNamedTuples.ts, 3, 65))
|
||||
|
||||
function fb2(a: NamedAnonymousMixed, ...args: NamedAnonymousMixed) {}
|
||||
>fb2 : Symbol(fb2, Decl(partiallyNamedTuples.ts, 7, 45))
|
||||
>a : Symbol(a, Decl(partiallyNamedTuples.ts, 8, 13))
|
||||
>NamedAnonymousMixed : Symbol(NamedAnonymousMixed, Decl(partiallyNamedTuples.ts, 3, 65))
|
||||
>args : Symbol(args, Decl(partiallyNamedTuples.ts, 8, 36))
|
||||
>NamedAnonymousMixed : Symbol(NamedAnonymousMixed, Decl(partiallyNamedTuples.ts, 3, 65))
|
||||
|
||||
function fb3(a: NamedAnonymousMixed, ...args: NamedAnonymousMixed[3]) {}
|
||||
>fb3 : Symbol(fb3, Decl(partiallyNamedTuples.ts, 8, 69))
|
||||
>a : Symbol(a, Decl(partiallyNamedTuples.ts, 9, 13))
|
||||
>NamedAnonymousMixed : Symbol(NamedAnonymousMixed, Decl(partiallyNamedTuples.ts, 3, 65))
|
||||
>args : Symbol(args, Decl(partiallyNamedTuples.ts, 9, 36))
|
||||
>NamedAnonymousMixed : Symbol(NamedAnonymousMixed, Decl(partiallyNamedTuples.ts, 3, 65))
|
||||
|
||||
type ToAnonymousTuple<T extends unknown[]> = {
|
||||
>ToAnonymousTuple : Symbol(ToAnonymousTuple, Decl(partiallyNamedTuples.ts, 9, 72))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 11, 22))
|
||||
|
||||
[K in keyof T]: [K, T[K], keyof T, T];
|
||||
>K : Symbol(K, Decl(partiallyNamedTuples.ts, 12, 3))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 11, 22))
|
||||
>K : Symbol(K, Decl(partiallyNamedTuples.ts, 12, 3))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 11, 22))
|
||||
>K : Symbol(K, Decl(partiallyNamedTuples.ts, 12, 3))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 11, 22))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 11, 22))
|
||||
|
||||
};
|
||||
|
||||
type AnonymousToAnonymous = ToAnonymousTuple<[boolean, number]>;
|
||||
>AnonymousToAnonymous : Symbol(AnonymousToAnonymous, Decl(partiallyNamedTuples.ts, 13, 2))
|
||||
>ToAnonymousTuple : Symbol(ToAnonymousTuple, Decl(partiallyNamedTuples.ts, 9, 72))
|
||||
|
||||
type MixedToAnonymous = ToAnonymousTuple<[boolean, second: number]>;
|
||||
>MixedToAnonymous : Symbol(MixedToAnonymous, Decl(partiallyNamedTuples.ts, 15, 64))
|
||||
>ToAnonymousTuple : Symbol(ToAnonymousTuple, Decl(partiallyNamedTuples.ts, 9, 72))
|
||||
|
||||
type NamedToAnonymous = ToAnonymousTuple<[first: boolean, second: number]>;
|
||||
>NamedToAnonymous : Symbol(NamedToAnonymous, Decl(partiallyNamedTuples.ts, 16, 68))
|
||||
>ToAnonymousTuple : Symbol(ToAnonymousTuple, Decl(partiallyNamedTuples.ts, 9, 72))
|
||||
|
||||
type ToMixedTuple<T extends unknown[]> = {
|
||||
>ToMixedTuple : Symbol(ToMixedTuple, Decl(partiallyNamedTuples.ts, 17, 75))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 19, 18))
|
||||
|
||||
[K in keyof T]: [K, second: T[K], keyof T, fourth: T];
|
||||
>K : Symbol(K, Decl(partiallyNamedTuples.ts, 20, 3))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 19, 18))
|
||||
>K : Symbol(K, Decl(partiallyNamedTuples.ts, 20, 3))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 19, 18))
|
||||
>K : Symbol(K, Decl(partiallyNamedTuples.ts, 20, 3))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 19, 18))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 19, 18))
|
||||
|
||||
};
|
||||
|
||||
type AnonymousToMixed = ToMixedTuple<[boolean, number]>;
|
||||
>AnonymousToMixed : Symbol(AnonymousToMixed, Decl(partiallyNamedTuples.ts, 21, 2))
|
||||
>ToMixedTuple : Symbol(ToMixedTuple, Decl(partiallyNamedTuples.ts, 17, 75))
|
||||
|
||||
type MixedToMixed = ToMixedTuple<[boolean, second: number]>;
|
||||
>MixedToMixed : Symbol(MixedToMixed, Decl(partiallyNamedTuples.ts, 23, 56))
|
||||
>ToMixedTuple : Symbol(ToMixedTuple, Decl(partiallyNamedTuples.ts, 17, 75))
|
||||
|
||||
type NamedToMixed = ToMixedTuple<[first: boolean, second: number]>;
|
||||
>NamedToMixed : Symbol(NamedToMixed, Decl(partiallyNamedTuples.ts, 24, 60))
|
||||
>ToMixedTuple : Symbol(ToMixedTuple, Decl(partiallyNamedTuples.ts, 17, 75))
|
||||
|
||||
type MixedSpread = [first: boolean, ...[second: string]];
|
||||
>MixedSpread : Symbol(MixedSpread, Decl(partiallyNamedTuples.ts, 25, 67))
|
||||
|
||||
type ConditionalTuple = [
|
||||
>ConditionalTuple : Symbol(ConditionalTuple, Decl(partiallyNamedTuples.ts, 27, 57))
|
||||
|
||||
first: boolean,
|
||||
...(0 extends 0 ? [second: string] : [])
|
||||
];
|
||||
|
||||
type AddMixedConditional<T> = [
|
||||
>AddMixedConditional : Symbol(AddMixedConditional, Decl(partiallyNamedTuples.ts, 32, 2))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 34, 25))
|
||||
|
||||
first: boolean,
|
||||
null,
|
||||
third: T extends number ? "a" : "b",
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 34, 25))
|
||||
|
||||
...(T extends 0 ? [fourth: "c"] : [])
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 34, 25))
|
||||
|
||||
];
|
||||
|
||||
type AddMixedConditionalBoolean = AddMixedConditional<boolean>;
|
||||
>AddMixedConditionalBoolean : Symbol(AddMixedConditionalBoolean, Decl(partiallyNamedTuples.ts, 39, 2))
|
||||
>AddMixedConditional : Symbol(AddMixedConditional, Decl(partiallyNamedTuples.ts, 32, 2))
|
||||
|
||||
type AddMixedConditionalLiteral = AddMixedConditional<0>;
|
||||
>AddMixedConditionalLiteral : Symbol(AddMixedConditionalLiteral, Decl(partiallyNamedTuples.ts, 41, 63))
|
||||
>AddMixedConditional : Symbol(AddMixedConditional, Decl(partiallyNamedTuples.ts, 32, 2))
|
||||
|
||||
type AddMixedConditionalNumberPrimitive = AddMixedConditional<number>;
|
||||
>AddMixedConditionalNumberPrimitive : Symbol(AddMixedConditionalNumberPrimitive, Decl(partiallyNamedTuples.ts, 42, 57))
|
||||
>AddMixedConditional : Symbol(AddMixedConditional, Decl(partiallyNamedTuples.ts, 32, 2))
|
||||
|
||||
declare function test<T extends readonly unknown[]>(
|
||||
>test : Symbol(test, Decl(partiallyNamedTuples.ts, 43, 70))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 45, 22))
|
||||
|
||||
arg: [
|
||||
>arg : Symbol(arg, Decl(partiallyNamedTuples.ts, 45, 52))
|
||||
|
||||
...{
|
||||
[K in keyof T]: {
|
||||
>K : Symbol(K, Decl(partiallyNamedTuples.ts, 48, 7))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 45, 22))
|
||||
|
||||
type: T[K];
|
||||
>type : Symbol(type, Decl(partiallyNamedTuples.ts, 48, 23))
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 45, 22))
|
||||
>K : Symbol(K, Decl(partiallyNamedTuples.ts, 48, 7))
|
||||
|
||||
};
|
||||
}
|
||||
]
|
||||
): T;
|
||||
>T : Symbol(T, Decl(partiallyNamedTuples.ts, 45, 22))
|
||||
|
||||
declare const input: [first: { type: number }, { type: string }];
|
||||
>input : Symbol(input, Decl(partiallyNamedTuples.ts, 55, 13))
|
||||
>type : Symbol(type, Decl(partiallyNamedTuples.ts, 55, 30))
|
||||
>type : Symbol(type, Decl(partiallyNamedTuples.ts, 55, 48))
|
||||
|
||||
const output = test(input);
|
||||
>output : Symbol(output, Decl(partiallyNamedTuples.ts, 57, 5))
|
||||
>test : Symbol(test, Decl(partiallyNamedTuples.ts, 43, 70))
|
||||
>input : Symbol(input, Decl(partiallyNamedTuples.ts, 55, 13))
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
//// [tests/cases/conformance/types/tuple/named/partiallyNamedTuples.ts] ////
|
||||
|
||||
=== partiallyNamedTuples.ts ===
|
||||
type NamedAndAnonymous = [a: string, number];
|
||||
>NamedAndAnonymous : [a: string, number]
|
||||
|
||||
function fa1(...args: NamedAndAnonymous) {}
|
||||
>fa1 : (a: string, args_1: number) => void
|
||||
>args : NamedAndAnonymous
|
||||
|
||||
function fa2(a: NamedAndAnonymous, ...args: NamedAndAnonymous) {}
|
||||
>fa2 : (a: NamedAndAnonymous, a: string, args_1: number) => void
|
||||
>a : NamedAndAnonymous
|
||||
>args : NamedAndAnonymous
|
||||
|
||||
type NamedAnonymousMixed = [a: string, number, c: number, NamedAndAnonymous];
|
||||
>NamedAnonymousMixed : [a: string, number, c: number, NamedAndAnonymous]
|
||||
|
||||
function fb1(...args: NamedAnonymousMixed) {}
|
||||
>fb1 : (a: string, args_1: number, c: number, args_3: NamedAndAnonymous) => void
|
||||
>args : NamedAnonymousMixed
|
||||
|
||||
function fb2(a: NamedAnonymousMixed, ...args: NamedAnonymousMixed) {}
|
||||
>fb2 : (a: NamedAnonymousMixed, a: string, args_1: number, c: number, args_3: NamedAndAnonymous) => void
|
||||
>a : NamedAnonymousMixed
|
||||
>args : NamedAnonymousMixed
|
||||
|
||||
function fb3(a: NamedAnonymousMixed, ...args: NamedAnonymousMixed[3]) {}
|
||||
>fb3 : (a: NamedAnonymousMixed, a: string, args_1: number) => void
|
||||
>a : NamedAnonymousMixed
|
||||
>args : NamedAndAnonymous
|
||||
|
||||
type ToAnonymousTuple<T extends unknown[]> = {
|
||||
>ToAnonymousTuple : ToAnonymousTuple<T>
|
||||
|
||||
[K in keyof T]: [K, T[K], keyof T, T];
|
||||
};
|
||||
|
||||
type AnonymousToAnonymous = ToAnonymousTuple<[boolean, number]>;
|
||||
>AnonymousToAnonymous : [["0", boolean, keyof [boolean, number], [boolean, number]], ["1", number, keyof [boolean, number], [boolean, number]]]
|
||||
|
||||
type MixedToAnonymous = ToAnonymousTuple<[boolean, second: number]>;
|
||||
>MixedToAnonymous : [["0", boolean, keyof [boolean, second: number], [boolean, second: number]], second: ["1", number, keyof [boolean, second: number], [boolean, second: number]]]
|
||||
|
||||
type NamedToAnonymous = ToAnonymousTuple<[first: boolean, second: number]>;
|
||||
>NamedToAnonymous : [first: ["0", boolean, keyof [first: boolean, second: number], [first: boolean, second: number]], second: ["1", number, keyof [first: boolean, second: number], [first: boolean, second: number]]]
|
||||
|
||||
type ToMixedTuple<T extends unknown[]> = {
|
||||
>ToMixedTuple : ToMixedTuple<T>
|
||||
|
||||
[K in keyof T]: [K, second: T[K], keyof T, fourth: T];
|
||||
};
|
||||
|
||||
type AnonymousToMixed = ToMixedTuple<[boolean, number]>;
|
||||
>AnonymousToMixed : [["0", second: boolean, keyof [boolean, number], fourth: [boolean, number]], ["1", second: number, keyof [boolean, number], fourth: [boolean, number]]]
|
||||
|
||||
type MixedToMixed = ToMixedTuple<[boolean, second: number]>;
|
||||
>MixedToMixed : [["0", second: boolean, keyof [boolean, second: number], fourth: [boolean, second: number]], second: ["1", second: number, keyof [boolean, second: number], fourth: [boolean, second: number]]]
|
||||
|
||||
type NamedToMixed = ToMixedTuple<[first: boolean, second: number]>;
|
||||
>NamedToMixed : [first: ["0", second: boolean, keyof [first: boolean, second: number], fourth: [first: boolean, second: number]], second: ["1", second: number, keyof [first: boolean, second: number], fourth: [first: boolean, second: number]]]
|
||||
|
||||
type MixedSpread = [first: boolean, ...[second: string]];
|
||||
>MixedSpread : [first: boolean, second: string]
|
||||
|
||||
type ConditionalTuple = [
|
||||
>ConditionalTuple : [first: boolean, second: string]
|
||||
|
||||
first: boolean,
|
||||
...(0 extends 0 ? [second: string] : [])
|
||||
];
|
||||
|
||||
type AddMixedConditional<T> = [
|
||||
>AddMixedConditional : [first: boolean, null, third: T extends number ? "a" : "b", ...T extends 0 ? [fourth: "c"] : []]
|
||||
|
||||
first: boolean,
|
||||
null,
|
||||
third: T extends number ? "a" : "b",
|
||||
...(T extends 0 ? [fourth: "c"] : [])
|
||||
];
|
||||
|
||||
type AddMixedConditionalBoolean = AddMixedConditional<boolean>;
|
||||
>AddMixedConditionalBoolean : [first: boolean, null, third: "b"]
|
||||
|
||||
type AddMixedConditionalLiteral = AddMixedConditional<0>;
|
||||
>AddMixedConditionalLiteral : [first: boolean, null, third: "a", fourth: "c"]
|
||||
|
||||
type AddMixedConditionalNumberPrimitive = AddMixedConditional<number>;
|
||||
>AddMixedConditionalNumberPrimitive : [first: boolean, null, third: "a"]
|
||||
|
||||
declare function test<T extends readonly unknown[]>(
|
||||
>test : <T extends readonly unknown[]>(arg: [...{ [K in keyof T]: { type: T[K]; }; }]) => T
|
||||
|
||||
arg: [
|
||||
>arg : [...{ [K in keyof T]: { type: T[K]; }; }]
|
||||
|
||||
...{
|
||||
[K in keyof T]: {
|
||||
type: T[K];
|
||||
>type : T[K]
|
||||
|
||||
};
|
||||
}
|
||||
]
|
||||
): T;
|
||||
|
||||
declare const input: [first: { type: number }, { type: string }];
|
||||
>input : [first: { type: number; }, { type: string; }]
|
||||
>type : number
|
||||
>type : string
|
||||
|
||||
const output = test(input);
|
||||
>output : [first: number, string]
|
||||
>test(input) : [first: number, string]
|
||||
>test : <T extends readonly unknown[]>(arg: [...{ [K in keyof T]: { type: T[K]; }; }]) => T
|
||||
>input : [first: { type: number; }, { type: string; }]
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// @declaration: true
|
||||
|
||||
export type Segment1 = [length: number, number]; // partially named, disallowed
|
||||
export type Segment2 = [number, size: number]; // partially named, disallowed
|
||||
export type Segment1 = [length: number, number];
|
||||
export type Segment2 = [number, size: number];
|
||||
|
||||
export type List = [item: any, ...any]; // partially named, disallowed
|
||||
export type List2 = [any, ...remainder: any]; // partially named, disallowed
|
||||
export type List = [item: any, ...any];
|
||||
export type List2 = [any, ...remainder: any];
|
||||
|
||||
export type Pair = [item: any, any?]; // partially named, disallowed
|
||||
export type Pair2 = [any, last?: any]; // partially named, disallowed
|
||||
export type Pair = [item: any, any?];
|
||||
export type Pair2 = [any, last?: any];
|
||||
|
||||
export type Opt = [element: string?]; // question mark on element disallowed
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
type NamedAndAnonymous = [a: string, number];
|
||||
|
||||
function fa1(...args: NamedAndAnonymous) {}
|
||||
function fa2(a: NamedAndAnonymous, ...args: NamedAndAnonymous) {}
|
||||
|
||||
type NamedAnonymousMixed = [a: string, number, c: number, NamedAndAnonymous];
|
||||
|
||||
function fb1(...args: NamedAnonymousMixed) {}
|
||||
function fb2(a: NamedAnonymousMixed, ...args: NamedAnonymousMixed) {}
|
||||
function fb3(a: NamedAnonymousMixed, ...args: NamedAnonymousMixed[3]) {}
|
||||
|
||||
type ToAnonymousTuple<T extends unknown[]> = {
|
||||
[K in keyof T]: [K, T[K], keyof T, T];
|
||||
};
|
||||
|
||||
type AnonymousToAnonymous = ToAnonymousTuple<[boolean, number]>;
|
||||
type MixedToAnonymous = ToAnonymousTuple<[boolean, second: number]>;
|
||||
type NamedToAnonymous = ToAnonymousTuple<[first: boolean, second: number]>;
|
||||
|
||||
type ToMixedTuple<T extends unknown[]> = {
|
||||
[K in keyof T]: [K, second: T[K], keyof T, fourth: T];
|
||||
};
|
||||
|
||||
type AnonymousToMixed = ToMixedTuple<[boolean, number]>;
|
||||
type MixedToMixed = ToMixedTuple<[boolean, second: number]>;
|
||||
type NamedToMixed = ToMixedTuple<[first: boolean, second: number]>;
|
||||
|
||||
type MixedSpread = [first: boolean, ...[second: string]];
|
||||
|
||||
type ConditionalTuple = [
|
||||
first: boolean,
|
||||
...(0 extends 0 ? [second: string] : [])
|
||||
];
|
||||
|
||||
type AddMixedConditional<T> = [
|
||||
first: boolean,
|
||||
null,
|
||||
third: T extends number ? "a" : "b",
|
||||
...(T extends 0 ? [fourth: "c"] : [])
|
||||
];
|
||||
|
||||
type AddMixedConditionalBoolean = AddMixedConditional<boolean>;
|
||||
type AddMixedConditionalLiteral = AddMixedConditional<0>;
|
||||
type AddMixedConditionalNumberPrimitive = AddMixedConditional<number>;
|
||||
|
||||
declare function test<T extends readonly unknown[]>(
|
||||
arg: [
|
||||
...{
|
||||
[K in keyof T]: {
|
||||
type: T[K];
|
||||
};
|
||||
}
|
||||
]
|
||||
): T;
|
||||
|
||||
declare const input: [first: { type: number }, { type: string }];
|
||||
|
||||
const output = test(input);
|
||||
Reference in New Issue
Block a user