@@ -971,6 +971,7 @@ namespace ts {
971
971
let deferredGlobalAsyncIterableIteratorType: GenericType | undefined;
972
972
let deferredGlobalAsyncGeneratorType: GenericType | undefined;
973
973
let deferredGlobalTemplateStringsArrayType: ObjectType | undefined;
974
+ let deferredGlobalTemplateStringsArrayOfSymbol: Symbol | undefined;
974
975
let deferredGlobalImportMetaType: ObjectType;
975
976
let deferredGlobalImportMetaExpressionType: ObjectType;
976
977
let deferredGlobalImportCallOptionsType: ObjectType | undefined;
@@ -14102,6 +14103,11 @@ namespace ts {
14102
14103
return (deferredGlobalBigIntType ||= getGlobalType("BigInt" as __String, /*arity*/ 0, /*reportErrors*/ false)) || emptyObjectType;
14103
14104
}
14104
14105
14106
+ function getGlobalTemplateStringsArrayOfSymbol(): Symbol | undefined {
14107
+ deferredGlobalTemplateStringsArrayOfSymbol ||= getGlobalTypeAliasSymbol("TemplateStringsArrayOf" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol;
14108
+ return deferredGlobalTemplateStringsArrayOfSymbol === unknownSymbol ? undefined : deferredGlobalTemplateStringsArrayOfSymbol;
14109
+ }
14110
+
14105
14111
/**
14106
14112
* Instantiates a global type that is generic with some element type, and returns that instantiation.
14107
14113
*/
@@ -21171,6 +21177,53 @@ namespace ts {
21171
21177
return isArrayType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType);
21172
21178
}
21173
21179
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
+
21174
21227
function getSingleBaseForNonAugmentingSubtype(type: Type) {
21175
21228
if (!(getObjectFlags(type) & ObjectFlags.Reference) || !(getObjectFlags((type as TypeReference).target) & ObjectFlags.ClassOrInterface)) {
21176
21229
return undefined;
@@ -22830,68 +22883,69 @@ namespace ts {
22830
22883
}
22831
22884
// Infer from the members of source and target only if the two types are possibly related
22832
22885
if (!typesDefinitelyUnrelated(source, target)) {
22833
- if (isArrayOrTupleType(source)) {
22886
+ const sourceArrayOrTuple = tryGetNonShadowedArrayOrTupleType(source);
22887
+ if (sourceArrayOrTuple) {
22834
22888
if (isTupleType(target)) {
22835
- const sourceArity = getTypeReferenceArity(source );
22889
+ const sourceArity = getTypeReferenceArity(sourceArrayOrTuple );
22836
22890
const targetArity = getTypeReferenceArity(target);
22837
22891
const elementTypes = getTypeArguments(target);
22838
22892
const elementFlags = target.target.elementFlags;
22839
22893
// When source and target are tuple types with the same structure (fixed, variadic, and rest are matched
22840
22894
// 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)) {
22842
22896
for (let i = 0; i < targetArity; i++) {
22843
- inferFromTypes(getTypeArguments(source )[i], elementTypes[i]);
22897
+ inferFromTypes(getTypeArguments(sourceArrayOrTuple )[i], elementTypes[i]);
22844
22898
}
22845
22899
return;
22846
22900
}
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,
22849
22903
target.target.hasRestElement ? getEndElementCount(target.target, ElementFlags.Fixed) : 0);
22850
22904
// Infer between starting fixed elements.
22851
22905
for (let i = 0; i < startLength; i++) {
22852
- inferFromTypes(getTypeArguments(source )[i], elementTypes[i]);
22906
+ inferFromTypes(getTypeArguments(sourceArrayOrTuple )[i], elementTypes[i]);
22853
22907
}
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) {
22855
22909
// 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];
22857
22911
for (let i = startLength; i < targetArity - endLength; i++) {
22858
22912
inferFromTypes(elementFlags[i] & ElementFlags.Variadic ? createArrayType(restType) : restType, elementTypes[i]);
22859
22913
}
22860
22914
}
22861
22915
else {
22862
22916
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 )) {
22864
22918
// Middle of target is [...T, ...U] and source is tuple type
22865
22919
const targetInfo = getInferenceInfoForType(elementTypes[startLength]);
22866
22920
if (targetInfo && targetInfo.impliedArity !== undefined) {
22867
22921
// 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]);
22870
22924
}
22871
22925
}
22872
22926
else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Variadic) {
22873
22927
// Middle of target is exactly one variadic element. Infer the slice between the fixed parts in the source.
22874
22928
// If target ends in optional element(s), make a lower priority a speculative inference.
22875
22929
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]);
22877
22931
inferWithPriority(sourceSlice, elementTypes[startLength], endsInOptional ? InferencePriority.SpeculativeTuple : 0);
22878
22932
}
22879
22933
else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Rest) {
22880
22934
// 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];
22882
22936
if (restType) {
22883
22937
inferFromTypes(restType, elementTypes[startLength]);
22884
22938
}
22885
22939
}
22886
22940
}
22887
22941
// Infer between ending fixed elements
22888
22942
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]);
22890
22944
}
22891
22945
return;
22892
22946
}
22893
22947
if (isArrayType(target)) {
22894
- inferFromIndexTypes(source , target);
22948
+ inferFromIndexTypes(sourceArrayOrTuple , target);
22895
22949
return;
22896
22950
}
22897
22951
}
@@ -27548,7 +27602,37 @@ namespace ts {
27548
27602
return checkIteratedTypeOrElementType(IterationUse.Spread, arrayOrIterableType, undefinedType, node.expression);
27549
27603
}
27550
27604
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
+
27551
27618
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
+ }
27552
27636
return node.isSpread ? getIndexedAccessType(node.type, numberType) : node.type;
27553
27637
}
27554
27638
@@ -30587,10 +30671,10 @@ namespace ts {
30587
30671
let typeArguments: NodeArray<TypeNode> | undefined;
30588
30672
30589
30673
if (!isDecorator) {
30590
- typeArguments = ( node as CallExpression) .typeArguments;
30674
+ typeArguments = node.typeArguments;
30591
30675
30592
30676
// 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) {
30594
30678
forEach(typeArguments, checkSourceElement);
30595
30679
}
30596
30680
}
@@ -35682,6 +35766,9 @@ namespace ts {
35682
35766
}
35683
35767
35684
35768
function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) {
35769
+ if (isTypeReferenceNode(node) && isIdentifier(node.typeName) && node.typeName.escapedText === "Scenario") {
35770
+ debugger;
35771
+ }
35685
35772
checkGrammarTypeArguments(node, node.typeArguments);
35686
35773
if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !isInJSFile(node) && !isInJSDoc(node)) {
35687
35774
grammarErrorAtPos(node, node.typeName.jsdocDotPos, 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments);
0 commit comments