@@ -971,6 +971,7 @@ namespace ts {
971971 let deferredGlobalAsyncIterableIteratorType: GenericType | undefined;
972972 let deferredGlobalAsyncGeneratorType: GenericType | undefined;
973973 let deferredGlobalTemplateStringsArrayType: ObjectType | undefined;
974+ let deferredGlobalTemplateStringsArrayOfSymbol: Symbol | undefined;
974975 let deferredGlobalImportMetaType: ObjectType;
975976 let deferredGlobalImportMetaExpressionType: ObjectType;
976977 let deferredGlobalImportCallOptionsType: ObjectType | undefined;
@@ -14102,6 +14103,11 @@ namespace ts {
1410214103 return (deferredGlobalBigIntType ||= getGlobalType("BigInt" as __String, /*arity*/ 0, /*reportErrors*/ false)) || emptyObjectType;
1410314104 }
1410414105
14106+ function getGlobalTemplateStringsArrayOfSymbol(): Symbol | undefined {
14107+ deferredGlobalTemplateStringsArrayOfSymbol ||= getGlobalTypeAliasSymbol("TemplateStringsArrayOf" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol;
14108+ return deferredGlobalTemplateStringsArrayOfSymbol === unknownSymbol ? undefined : deferredGlobalTemplateStringsArrayOfSymbol;
14109+ }
14110+
1410514111 /**
1410614112 * Instantiates a global type that is generic with some element type, and returns that instantiation.
1410714113 */
@@ -21171,6 +21177,53 @@ namespace ts {
2117121177 return isArrayType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType);
2117221178 }
2117321179
21180+ function tryGetNonShadowedArrayOrTupleType(type: Type) {
21181+ if (isArrayOrTupleType(type)) {
21182+ return type;
21183+ }
21184+
21185+ if (!(type.flags & TypeFlags.Intersection)) {
21186+ return undefined;
21187+ }
21188+
21189+ // pick an intersection constituent if it is an array or tuple type, but only
21190+ // if any non-array, non-tuple constituents that follow it do not shadow any
21191+ // tuple-specific members.
21192+ let arrayOrTuple: TypeReference | undefined;
21193+ let constituents: Type[] | undefined;
21194+ for (const constituent of (type as IntersectionType).types) {
21195+ if (isArrayOrTupleType(constituent)) {
21196+ arrayOrTuple = constituent;
21197+ constituents = undefined;
21198+ }
21199+ else {
21200+ constituents = append(constituents, constituent);
21201+ }
21202+ }
21203+
21204+ if (!arrayOrTuple || !constituents) {
21205+ return arrayOrTuple;
21206+ }
21207+
21208+ for (const constituent of constituents) {
21209+ if (!(constituent.flags & TypeFlags.Object)) continue;
21210+ const properties = getPropertiesOfType(constituent);
21211+ for (const property of properties) {
21212+ // consider numeric literal names or the string 'length' to be overlapping
21213+ if (isNumericLiteralName(property.escapedName) || property.escapedName === "length" as __String) {
21214+ return undefined;
21215+ }
21216+ }
21217+
21218+ // Consider a constituent to be overlapping if it contains an index signature that shadows array indexes
21219+ if (findApplicableIndexInfo(getIndexInfosOfType(constituent), numberType)) {
21220+ return undefined;
21221+ }
21222+ }
21223+
21224+ return arrayOrTuple;
21225+ }
21226+
2117421227 function getSingleBaseForNonAugmentingSubtype(type: Type) {
2117521228 if (!(getObjectFlags(type) & ObjectFlags.Reference) || !(getObjectFlags((type as TypeReference).target) & ObjectFlags.ClassOrInterface)) {
2117621229 return undefined;
@@ -22830,68 +22883,69 @@ namespace ts {
2283022883 }
2283122884 // Infer from the members of source and target only if the two types are possibly related
2283222885 if (!typesDefinitelyUnrelated(source, target)) {
22833- if (isArrayOrTupleType(source)) {
22886+ const sourceArrayOrTuple = tryGetNonShadowedArrayOrTupleType(source);
22887+ if (sourceArrayOrTuple) {
2283422888 if (isTupleType(target)) {
22835- const sourceArity = getTypeReferenceArity(source );
22889+ const sourceArity = getTypeReferenceArity(sourceArrayOrTuple );
2283622890 const targetArity = getTypeReferenceArity(target);
2283722891 const elementTypes = getTypeArguments(target);
2283822892 const elementFlags = target.target.elementFlags;
2283922893 // When source and target are tuple types with the same structure (fixed, variadic, and rest are matched
2284022894 // to the same kind in each position), simply infer between the element types.
22841- if (isTupleType(source ) && isTupleTypeStructureMatching(source , target)) {
22895+ if (isTupleType(sourceArrayOrTuple ) && isTupleTypeStructureMatching(sourceArrayOrTuple , target)) {
2284222896 for (let i = 0; i < targetArity; i++) {
22843- inferFromTypes(getTypeArguments(source )[i], elementTypes[i]);
22897+ inferFromTypes(getTypeArguments(sourceArrayOrTuple )[i], elementTypes[i]);
2284422898 }
2284522899 return;
2284622900 }
22847- const startLength = isTupleType(source ) ? Math.min(source .target.fixedLength, target.target.fixedLength) : 0;
22848- const endLength = Math.min(isTupleType(source ) ? getEndElementCount(source .target, ElementFlags.Fixed) : 0,
22901+ const startLength = isTupleType(sourceArrayOrTuple ) ? Math.min(sourceArrayOrTuple .target.fixedLength, target.target.fixedLength) : 0;
22902+ const endLength = Math.min(isTupleType(sourceArrayOrTuple ) ? getEndElementCount(sourceArrayOrTuple .target, ElementFlags.Fixed) : 0,
2284922903 target.target.hasRestElement ? getEndElementCount(target.target, ElementFlags.Fixed) : 0);
2285022904 // Infer between starting fixed elements.
2285122905 for (let i = 0; i < startLength; i++) {
22852- inferFromTypes(getTypeArguments(source )[i], elementTypes[i]);
22906+ inferFromTypes(getTypeArguments(sourceArrayOrTuple )[i], elementTypes[i]);
2285322907 }
22854- if (!isTupleType(source ) || sourceArity - startLength - endLength === 1 && source .target.elementFlags[startLength] & ElementFlags.Rest) {
22908+ if (!isTupleType(sourceArrayOrTuple ) || sourceArity - startLength - endLength === 1 && sourceArrayOrTuple .target.elementFlags[startLength] & ElementFlags.Rest) {
2285522909 // Single rest element remains in source, infer from that to every element in target
22856- const restType = getTypeArguments(source )[startLength];
22910+ const restType = getTypeArguments(sourceArrayOrTuple )[startLength];
2285722911 for (let i = startLength; i < targetArity - endLength; i++) {
2285822912 inferFromTypes(elementFlags[i] & ElementFlags.Variadic ? createArrayType(restType) : restType, elementTypes[i]);
2285922913 }
2286022914 }
2286122915 else {
2286222916 const middleLength = targetArity - startLength - endLength;
22863- if (middleLength === 2 && elementFlags[startLength] & elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(source )) {
22917+ if (middleLength === 2 && elementFlags[startLength] & elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(sourceArrayOrTuple )) {
2286422918 // Middle of target is [...T, ...U] and source is tuple type
2286522919 const targetInfo = getInferenceInfoForType(elementTypes[startLength]);
2286622920 if (targetInfo && targetInfo.impliedArity !== undefined) {
2286722921 // Infer slices from source based on implied arity of T.
22868- inferFromTypes(sliceTupleType(source , startLength, endLength + sourceArity - targetInfo.impliedArity), elementTypes[startLength]);
22869- inferFromTypes(sliceTupleType(source , startLength + targetInfo.impliedArity, endLength), elementTypes[startLength + 1]);
22922+ inferFromTypes(sliceTupleType(sourceArrayOrTuple , startLength, endLength + sourceArity - targetInfo.impliedArity), elementTypes[startLength]);
22923+ inferFromTypes(sliceTupleType(sourceArrayOrTuple , startLength + targetInfo.impliedArity, endLength), elementTypes[startLength + 1]);
2287022924 }
2287122925 }
2287222926 else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Variadic) {
2287322927 // Middle of target is exactly one variadic element. Infer the slice between the fixed parts in the source.
2287422928 // If target ends in optional element(s), make a lower priority a speculative inference.
2287522929 const endsInOptional = target.target.elementFlags[targetArity - 1] & ElementFlags.Optional;
22876- const sourceSlice = isTupleType(source ) ? sliceTupleType(source , startLength, endLength) : createArrayType(getTypeArguments(source )[0]);
22930+ const sourceSlice = isTupleType(sourceArrayOrTuple ) ? sliceTupleType(sourceArrayOrTuple , startLength, endLength) : createArrayType(getTypeArguments(sourceArrayOrTuple )[0]);
2287722931 inferWithPriority(sourceSlice, elementTypes[startLength], endsInOptional ? InferencePriority.SpeculativeTuple : 0);
2287822932 }
2287922933 else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Rest) {
2288022934 // Middle of target is exactly one rest element. If middle of source is not empty, infer union of middle element types.
22881- const restType = isTupleType(source ) ? getElementTypeOfSliceOfTupleType(source , startLength, endLength) : getTypeArguments(source )[0];
22935+ const restType = isTupleType(sourceArrayOrTuple ) ? getElementTypeOfSliceOfTupleType(sourceArrayOrTuple , startLength, endLength) : getTypeArguments(sourceArrayOrTuple )[0];
2288222936 if (restType) {
2288322937 inferFromTypes(restType, elementTypes[startLength]);
2288422938 }
2288522939 }
2288622940 }
2288722941 // Infer between ending fixed elements
2288822942 for (let i = 0; i < endLength; i++) {
22889- inferFromTypes(getTypeArguments(source )[sourceArity - i - 1], elementTypes[targetArity - i - 1]);
22943+ inferFromTypes(getTypeArguments(sourceArrayOrTuple )[sourceArity - i - 1], elementTypes[targetArity - i - 1]);
2289022944 }
2289122945 return;
2289222946 }
2289322947 if (isArrayType(target)) {
22894- inferFromIndexTypes(source , target);
22948+ inferFromIndexTypes(sourceArrayOrTuple , target);
2289522949 return;
2289622950 }
2289722951 }
@@ -27548,7 +27602,37 @@ namespace ts {
2754827602 return checkIteratedTypeOrElementType(IterationUse.Spread, arrayOrIterableType, undefinedType, node.expression);
2754927603 }
2755027604
27605+ function getTemplateStringsArrayOf(cookedTypes: Type[], rawTypes: Type[]) {
27606+ const templateStringsArrayOfAlias = getGlobalTemplateStringsArrayOfSymbol();
27607+ if (!templateStringsArrayOfAlias) return getGlobalTemplateStringsArrayType();
27608+ const cookedType = createTupleType(cookedTypes, /*elementFlags*/ undefined, /*readonly*/ true);
27609+ const rawType = createTupleType(rawTypes, /*elementFlags*/ undefined, /*readonly*/ true);
27610+ return getTypeAliasInstantiation(templateStringsArrayOfAlias, [cookedType, rawType]);
27611+ }
27612+
27613+ function getRawLiteralType(node: TemplateLiteralLikeNode) {
27614+ const text = getRawTextOfTemplateLiteralLike(node, getSourceFileOfNode(node));
27615+ return getStringLiteralType(text);
27616+ }
27617+
2755127618 function checkSyntheticExpression(node: SyntheticExpression): Type {
27619+ if (isTemplateLiteral(node.parent) && node.type === getGlobalTemplateStringsArrayType()) {
27620+ const cookedStrings: Type[] = [];
27621+ const rawStrings: Type[] = [];
27622+ if (isNoSubstitutionTemplateLiteral(node.parent)) {
27623+ cookedStrings.push(getStringLiteralType(node.parent.text));
27624+ rawStrings.push(getRawLiteralType(node.parent));
27625+ }
27626+ else {
27627+ cookedStrings.push(getStringLiteralType(node.parent.head.text));
27628+ rawStrings.push(getRawLiteralType(node.parent.head));
27629+ for (const templateSpan of node.parent.templateSpans) {
27630+ cookedStrings.push(getStringLiteralType(templateSpan.literal.text));
27631+ rawStrings.push(getRawLiteralType(templateSpan.literal));
27632+ }
27633+ }
27634+ return getTemplateStringsArrayOf(cookedStrings, rawStrings);
27635+ }
2755227636 return node.isSpread ? getIndexedAccessType(node.type, numberType) : node.type;
2755327637 }
2755427638
@@ -30587,10 +30671,10 @@ namespace ts {
3058730671 let typeArguments: NodeArray<TypeNode> | undefined;
3058830672
3058930673 if (!isDecorator) {
30590- typeArguments = ( node as CallExpression) .typeArguments;
30674+ typeArguments = node.typeArguments;
3059130675
3059230676 // We already perform checking on the type arguments on the class declaration itself.
30593- if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || ( node as CallExpression) .expression.kind !== SyntaxKind.SuperKeyword) {
30677+ if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || node.expression.kind !== SyntaxKind.SuperKeyword) {
3059430678 forEach(typeArguments, checkSourceElement);
3059530679 }
3059630680 }
@@ -35682,6 +35766,9 @@ namespace ts {
3568235766 }
3568335767
3568435768 function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) {
35769+ if (isTypeReferenceNode(node) && isIdentifier(node.typeName) && node.typeName.escapedText === "Scenario") {
35770+ debugger;
35771+ }
3568535772 checkGrammarTypeArguments(node, node.typeArguments);
3568635773 if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !isInJSFile(node) && !isInJSDoc(node)) {
3568735774 grammarErrorAtPos(node, node.typeName.jsdocDotPos, 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments);
0 commit comments