From 70fdb520b258d1f4a83fb714e89c4e0be2d1a19b Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 14 Jun 2022 19:15:55 -0700 Subject: [PATCH 1/3] More specific TemplateStringsArray type for tagged templates --- src/compiler/checker.ts | 110 ++++++++++-- src/compiler/transformers/taggedTemplate.ts | 22 +-- src/compiler/utilities.ts | 24 +++ src/harness/fourslashInterfaceImpl.ts | 1 + src/lib/es5.d.ts | 2 + ...tructuringParameterDeclaration4.errors.txt | 2 +- .../reference/destructuringTuple.errors.txt | 4 +- .../duplicateNumericIndexers.errors.txt | 2 +- .../reference/externModule.errors.txt | 8 +- tests/baselines/reference/importHelpers.types | 8 +- .../reference/inferTypes1.errors.txt | 4 + tests/baselines/reference/inferTypes1.js | 4 + tests/baselines/reference/inferTypes1.symbols | 14 ++ tests/baselines/reference/inferTypes1.types | 8 + ...ithAsClauseAndLateBoundProperty.errors.txt | 2 +- ...wExceptionVariableInCatchClause.errors.txt | 2 +- .../narrowFromAnyWithInstanceof.errors.txt | 4 +- .../narrowFromAnyWithTypePredicate.errors.txt | 4 +- .../reference/parserS7.2_A1.5_T2.errors.txt | 4 +- .../reference/parserS7.3_A1.1_T2.errors.txt | 2 +- .../reference/parserS7.6_A4.2_T1.errors.txt | 20 +-- .../reference/parserUnicode1.errors.txt | 4 +- .../reference/promisePermutations.errors.txt | 2 +- .../reference/promisePermutations2.errors.txt | 2 +- .../reference/promisePermutations3.errors.txt | 4 +- .../reference/redefineArray.errors.txt | 2 +- .../reference/scannerS7.2_A1.5_T2.errors.txt | 4 +- .../reference/scannerS7.3_A1.1_T2.errors.txt | 2 +- .../reference/scannerS7.6_A4.2_T1.errors.txt | 20 +-- ...emplateWithSpecificTemplateStrings.symbols | 160 ++++++++++++++++++ ...dTemplateWithSpecificTemplateStrings.types | 143 ++++++++++++++++ .../taggedTemplateWithoutDeclaredHelper.types | 4 +- .../taggedTemplatesInModuleAndGlobal.types | 24 +-- ...ggedTemplateWithSpecificTemplateStrings.ts | 45 +++++ .../types/conditional/inferTypes1.ts | 4 + 35 files changed, 567 insertions(+), 104 deletions(-) create mode 100644 tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols create mode 100644 tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types create mode 100644 tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 96eb829559889..6f190bf74c64d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -971,6 +971,7 @@ namespace ts { let deferredGlobalAsyncIterableIteratorType: GenericType | undefined; let deferredGlobalAsyncGeneratorType: GenericType | undefined; let deferredGlobalTemplateStringsArrayType: ObjectType | undefined; + let deferredGlobalTemplateStringsArrayOfSymbol: Symbol | undefined; let deferredGlobalImportMetaType: ObjectType; let deferredGlobalImportMetaExpressionType: ObjectType; let deferredGlobalImportCallOptionsType: ObjectType | undefined; @@ -14102,6 +14103,11 @@ namespace ts { return (deferredGlobalBigIntType ||= getGlobalType("BigInt" as __String, /*arity*/ 0, /*reportErrors*/ false)) || emptyObjectType; } + function getGlobalTemplateStringsArrayOfSymbol(): Symbol | undefined { + deferredGlobalTemplateStringsArrayOfSymbol ||= getGlobalTypeAliasSymbol("TemplateStringsArrayOf" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol; + return deferredGlobalTemplateStringsArrayOfSymbol === unknownSymbol ? undefined : deferredGlobalTemplateStringsArrayOfSymbol; + } + /** * Instantiates a global type that is generic with some element type, and returns that instantiation. */ @@ -21171,6 +21177,43 @@ namespace ts { return isArrayType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType); } + /** + * Returns `type` if it is an array or tuple type. If `type` is an intersection type, + * returns the rightmost constituent that is an array or tuple type, but only if there are no + * other constituents to that contain properties that overlap with array- or tuple- specific + * members (i.e., index signatures, numeric string property names, or `length`). + */ + function tryGetNonShadowedArrayOrTupleType(type: Type) { + if (isArrayOrTupleType(type)) { + return type; + } + + if (!(type.flags & TypeFlags.Intersection)) { + return undefined; + } + + let arrayOrTupleConstituent: TypeReference | undefined; + for (const constituent of (type as IntersectionType).types) { + if (isArrayOrTupleType(constituent)) { + arrayOrTupleConstituent = constituent; + } + else { + const properties = getPropertiesOfType(constituent); + for (const property of properties) { + if (isNumericLiteralName(property.escapedName) || property.escapedName === "length" as __String) { + return undefined; + } + } + + if (some(getIndexInfosOfType(constituent))) { + return undefined; + } + } + } + + return arrayOrTupleConstituent; + } + function getSingleBaseForNonAugmentingSubtype(type: Type) { if (!(getObjectFlags(type) & ObjectFlags.Reference) || !(getObjectFlags((type as TypeReference).target) & ObjectFlags.ClassOrInterface)) { return undefined; @@ -22830,55 +22873,56 @@ namespace ts { } // Infer from the members of source and target only if the two types are possibly related if (!typesDefinitelyUnrelated(source, target)) { - if (isArrayOrTupleType(source)) { + const sourceArrayOrTuple = tryGetNonShadowedArrayOrTupleType(source); + if (sourceArrayOrTuple) { if (isTupleType(target)) { - const sourceArity = getTypeReferenceArity(source); + const sourceArity = getTypeReferenceArity(sourceArrayOrTuple); const targetArity = getTypeReferenceArity(target); const elementTypes = getTypeArguments(target); const elementFlags = target.target.elementFlags; // When source and target are tuple types with the same structure (fixed, variadic, and rest are matched // to the same kind in each position), simply infer between the element types. - if (isTupleType(source) && isTupleTypeStructureMatching(source, target)) { + if (isTupleType(sourceArrayOrTuple) && isTupleTypeStructureMatching(sourceArrayOrTuple, target)) { for (let i = 0; i < targetArity; i++) { - inferFromTypes(getTypeArguments(source)[i], elementTypes[i]); + inferFromTypes(getTypeArguments(sourceArrayOrTuple)[i], elementTypes[i]); } return; } - const startLength = isTupleType(source) ? Math.min(source.target.fixedLength, target.target.fixedLength) : 0; - const endLength = Math.min(isTupleType(source) ? getEndElementCount(source.target, ElementFlags.Fixed) : 0, + const startLength = isTupleType(sourceArrayOrTuple) ? Math.min(sourceArrayOrTuple.target.fixedLength, target.target.fixedLength) : 0; + const endLength = Math.min(isTupleType(sourceArrayOrTuple) ? getEndElementCount(sourceArrayOrTuple.target, ElementFlags.Fixed) : 0, target.target.hasRestElement ? getEndElementCount(target.target, ElementFlags.Fixed) : 0); // Infer between starting fixed elements. for (let i = 0; i < startLength; i++) { - inferFromTypes(getTypeArguments(source)[i], elementTypes[i]); + inferFromTypes(getTypeArguments(sourceArrayOrTuple)[i], elementTypes[i]); } - if (!isTupleType(source) || sourceArity - startLength - endLength === 1 && source.target.elementFlags[startLength] & ElementFlags.Rest) { + if (!isTupleType(sourceArrayOrTuple) || sourceArity - startLength - endLength === 1 && sourceArrayOrTuple.target.elementFlags[startLength] & ElementFlags.Rest) { // Single rest element remains in source, infer from that to every element in target - const restType = getTypeArguments(source)[startLength]; + const restType = getTypeArguments(sourceArrayOrTuple)[startLength]; for (let i = startLength; i < targetArity - endLength; i++) { inferFromTypes(elementFlags[i] & ElementFlags.Variadic ? createArrayType(restType) : restType, elementTypes[i]); } } else { const middleLength = targetArity - startLength - endLength; - if (middleLength === 2 && elementFlags[startLength] & elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(source)) { + if (middleLength === 2 && elementFlags[startLength] & elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(sourceArrayOrTuple)) { // Middle of target is [...T, ...U] and source is tuple type const targetInfo = getInferenceInfoForType(elementTypes[startLength]); if (targetInfo && targetInfo.impliedArity !== undefined) { // Infer slices from source based on implied arity of T. - inferFromTypes(sliceTupleType(source, startLength, endLength + sourceArity - targetInfo.impliedArity), elementTypes[startLength]); - inferFromTypes(sliceTupleType(source, startLength + targetInfo.impliedArity, endLength), elementTypes[startLength + 1]); + inferFromTypes(sliceTupleType(sourceArrayOrTuple, startLength, endLength + sourceArity - targetInfo.impliedArity), elementTypes[startLength]); + inferFromTypes(sliceTupleType(sourceArrayOrTuple, startLength + targetInfo.impliedArity, endLength), elementTypes[startLength + 1]); } } else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Variadic) { // Middle of target is exactly one variadic element. Infer the slice between the fixed parts in the source. // If target ends in optional element(s), make a lower priority a speculative inference. const endsInOptional = target.target.elementFlags[targetArity - 1] & ElementFlags.Optional; - const sourceSlice = isTupleType(source) ? sliceTupleType(source, startLength, endLength) : createArrayType(getTypeArguments(source)[0]); + const sourceSlice = isTupleType(sourceArrayOrTuple) ? sliceTupleType(sourceArrayOrTuple, startLength, endLength) : createArrayType(getTypeArguments(sourceArrayOrTuple)[0]); inferWithPriority(sourceSlice, elementTypes[startLength], endsInOptional ? InferencePriority.SpeculativeTuple : 0); } else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Rest) { // Middle of target is exactly one rest element. If middle of source is not empty, infer union of middle element types. - const restType = isTupleType(source) ? getElementTypeOfSliceOfTupleType(source, startLength, endLength) : getTypeArguments(source)[0]; + const restType = isTupleType(sourceArrayOrTuple) ? getElementTypeOfSliceOfTupleType(sourceArrayOrTuple, startLength, endLength) : getTypeArguments(sourceArrayOrTuple)[0]; if (restType) { inferFromTypes(restType, elementTypes[startLength]); } @@ -22886,12 +22930,12 @@ namespace ts { } // Infer between ending fixed elements for (let i = 0; i < endLength; i++) { - inferFromTypes(getTypeArguments(source)[sourceArity - i - 1], elementTypes[targetArity - i - 1]); + inferFromTypes(getTypeArguments(sourceArrayOrTuple)[sourceArity - i - 1], elementTypes[targetArity - i - 1]); } return; } if (isArrayType(target)) { - inferFromIndexTypes(source, target); + inferFromIndexTypes(sourceArrayOrTuple, target); return; } } @@ -27548,7 +27592,37 @@ namespace ts { return checkIteratedTypeOrElementType(IterationUse.Spread, arrayOrIterableType, undefinedType, node.expression); } + function getTemplateStringsArrayOf(cookedTypes: Type[], rawTypes: Type[]) { + const templateStringsArrayOfAlias = getGlobalTemplateStringsArrayOfSymbol(); + if (!templateStringsArrayOfAlias) return getGlobalTemplateStringsArrayType(); + const cookedType = createTupleType(cookedTypes, /*elementFlags*/ undefined, /*readonly*/ true); + const rawType = createTupleType(rawTypes, /*elementFlags*/ undefined, /*readonly*/ true); + return getTypeAliasInstantiation(templateStringsArrayOfAlias, [cookedType, rawType]); + } + + function getRawLiteralType(node: TemplateLiteralLikeNode) { + const text = getRawTextOfTemplateLiteralLike(node, getSourceFileOfNode(node)); + return getStringLiteralType(text); + } + function checkSyntheticExpression(node: SyntheticExpression): Type { + if (isTemplateLiteral(node.parent) && node.type === getGlobalTemplateStringsArrayType()) { + const cookedStrings: Type[] = []; + const rawStrings: Type[] = []; + if (isNoSubstitutionTemplateLiteral(node.parent)) { + cookedStrings.push(getStringLiteralType(node.parent.text)); + rawStrings.push(getRawLiteralType(node.parent)); + } + else { + cookedStrings.push(getStringLiteralType(node.parent.head.text)); + rawStrings.push(getRawLiteralType(node.parent.head)); + for (const templateSpan of node.parent.templateSpans) { + cookedStrings.push(getStringLiteralType(templateSpan.literal.text)); + rawStrings.push(getRawLiteralType(templateSpan.literal)); + } + } + return getTemplateStringsArrayOf(cookedStrings, rawStrings); + } return node.isSpread ? getIndexedAccessType(node.type, numberType) : node.type; } @@ -30587,10 +30661,10 @@ namespace ts { let typeArguments: NodeArray | undefined; if (!isDecorator) { - typeArguments = (node as CallExpression).typeArguments; + typeArguments = node.typeArguments; // We already perform checking on the type arguments on the class declaration itself. - if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || (node as CallExpression).expression.kind !== SyntaxKind.SuperKeyword) { + if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || node.expression.kind !== SyntaxKind.SuperKeyword) { forEach(typeArguments, checkSourceElement); } } diff --git a/src/compiler/transformers/taggedTemplate.ts b/src/compiler/transformers/taggedTemplate.ts index 60b37c1018f49..2007511032cce 100644 --- a/src/compiler/transformers/taggedTemplate.ts +++ b/src/compiler/transformers/taggedTemplate.ts @@ -76,27 +76,7 @@ namespace ts { * @param node The ES6 template literal. */ function getRawLiteral(node: TemplateLiteralLikeNode, currentSourceFile: SourceFile) { - // Find original source text, since we need to emit the raw strings of the tagged template. - // The raw strings contain the (escaped) strings of what the user wrote. - // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". - let text = node.rawText; - if (text === undefined) { - Debug.assertIsDefined(currentSourceFile, - "Template literal node is missing 'rawText' and does not have a source file. Possibly bad transform."); - text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node); - - // text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"), - // thus we need to remove those characters. - // First template piece starts with "`", others with "}" - // Last template piece ends with "`", others with "${" - const isLast = node.kind === SyntaxKind.NoSubstitutionTemplateLiteral || node.kind === SyntaxKind.TemplateTail; - text = text.substring(1, text.length - (isLast ? 1 : 2)); - } - - // Newline normalization: - // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's - // and LineTerminatorSequences are normalized to for both TV and TRV. - text = text.replace(/\r\n?/g, "\n"); + const text = getRawTextOfTemplateLiteralLike(node, currentSourceFile); return setTextRange(factory.createStringLiteral(text), node); } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 0ac57b26fee15..331038ce8253f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -713,6 +713,30 @@ namespace ts { return Debug.fail(`Literal kind '${node.kind}' not accounted for.`); } + export function getRawTextOfTemplateLiteralLike(node: TemplateLiteralLikeNode, sourceFile: SourceFile) { + // Find original source text, since we need to emit the raw strings of the tagged template. + // The raw strings contain the (escaped) strings of what the user wrote. + // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". + let text = node.rawText; + if (text === undefined) { + Debug.assertIsDefined(sourceFile, + "Template literal node is missing 'rawText' and does not have a source file. Possibly bad transform."); + text = getSourceTextOfNodeFromSourceFile(sourceFile, node); + + // text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"), + // thus we need to remove those characters. + // First template piece starts with "`", others with "}" + // Last template piece ends with "`", others with "${" + const isLast = node.kind === SyntaxKind.NoSubstitutionTemplateLiteral || node.kind === SyntaxKind.TemplateTail; + text = text.substring(1, text.length - (isLast ? 1 : 2)); + } + + // Newline normalization: + // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's + // and LineTerminatorSequences are normalized to for both TV and TRV. + return text.replace(/\r\n?/g, "\n"); + } + function canUseOriginalText(node: LiteralLikeNode, flags: GetLiteralTextFlags): boolean { if (nodeIsSynthesized(node) || !node.parent || (flags & GetLiteralTextFlags.TerminateUnterminatedLiterals && node.isUnterminated)) { return false; diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index ab830bb0a5ed7..fa5b68fc6f9de 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -1119,6 +1119,7 @@ namespace FourSlashInterface { varEntry("Number"), interfaceEntry("NumberConstructor"), interfaceEntry("TemplateStringsArray"), + typeEntry("TemplateStringsArrayOf"), interfaceEntry("ImportMeta"), interfaceEntry("ImportCallOptions"), interfaceEntry("ImportAssertions"), diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 754f6655db1a6..81a5c12169fba 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -594,6 +594,8 @@ interface TemplateStringsArray extends ReadonlyArray { readonly raw: readonly string[]; } +type TemplateStringsArrayOf = Cooked & { readonly raw: Raw }; + /** * The type of `import.meta`. * diff --git a/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt index 4f9b905252e09..353c921a0661d 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt @@ -41,7 +41,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts( a1(...array2); // Error parameter type is (number|string)[] ~~~~~~ !!! error TS2552: Cannot find name 'array2'. Did you mean 'Array'? -!!! related TS2728 /.ts/lib.es5.d.ts:1470:13: 'Array' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1472:13: 'Array' is declared here. a5([1, 2, "string", false, true]); // Error, parameter type is [any, any, [[any]]] ~~~~~~~~ !!! error TS2322: Type 'string' is not assignable to type '[[any]]'. diff --git a/tests/baselines/reference/destructuringTuple.errors.txt b/tests/baselines/reference/destructuringTuple.errors.txt index e343fa4fade70..6a1c870a0b5c7 100644 --- a/tests/baselines/reference/destructuringTuple.errors.txt +++ b/tests/baselines/reference/destructuringTuple.errors.txt @@ -33,8 +33,8 @@ tests/cases/compiler/destructuringTuple.ts(11,60): error TS2769: No overload mat !!! error TS2769: Overload 2 of 3, '(callbackfn: (previousValue: [], currentValue: number, currentIndex: number, array: number[]) => [], initialValue: []): []', gave the following error. !!! error TS2769: Type 'never[]' is not assignable to type '[]'. !!! error TS2769: Target allows only 0 element(s) but source may have more. -!!! related TS6502 /.ts/lib.es5.d.ts:1435:24: The expected type comes from the return type of this signature. -!!! related TS6502 /.ts/lib.es5.d.ts:1441:27: The expected type comes from the return type of this signature. +!!! related TS6502 /.ts/lib.es5.d.ts:1437:24: The expected type comes from the return type of this signature. +!!! related TS6502 /.ts/lib.es5.d.ts:1443:27: The expected type comes from the return type of this signature. ~~ !!! error TS2769: No overload matches this call. !!! error TS2769: Overload 1 of 2, '(...items: ConcatArray[]): never[]', gave the following error. diff --git a/tests/baselines/reference/duplicateNumericIndexers.errors.txt b/tests/baselines/reference/duplicateNumericIndexers.errors.txt index e0eb2d237056c..27b4ddda977c9 100644 --- a/tests/baselines/reference/duplicateNumericIndexers.errors.txt +++ b/tests/baselines/reference/duplicateNumericIndexers.errors.txt @@ -11,7 +11,7 @@ tests/cases/conformance/types/members/duplicateNumericIndexers.ts(25,5): error T tests/cases/conformance/types/members/duplicateNumericIndexers.ts(29,5): error TS2374: Duplicate index signature for type 'number'. tests/cases/conformance/types/members/duplicateNumericIndexers.ts(30,5): error TS2374: Duplicate index signature for type 'number'. lib.es5.d.ts(523,5): error TS2374: Duplicate index signature for type 'number'. -lib.es5.d.ts(1456,5): error TS2374: Duplicate index signature for type 'number'. +lib.es5.d.ts(1458,5): error TS2374: Duplicate index signature for type 'number'. ==== tests/cases/conformance/types/members/duplicateNumericIndexers.ts (12 errors) ==== diff --git a/tests/baselines/reference/externModule.errors.txt b/tests/baselines/reference/externModule.errors.txt index db7d505bba102..2e3192bb63662 100644 --- a/tests/baselines/reference/externModule.errors.txt +++ b/tests/baselines/reference/externModule.errors.txt @@ -66,20 +66,20 @@ tests/cases/compiler/externModule.ts(37,3): error TS2552: Cannot find name 'XDat var d=new XDate(); ~~~~~ !!! error TS2552: Cannot find name 'XDate'. Did you mean 'Date'? -!!! related TS2728 /.ts/lib.es5.d.ts:933:13: 'Date' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:935:13: 'Date' is declared here. d.getDay(); d=new XDate(1978,2); ~~~~~ !!! error TS2552: Cannot find name 'XDate'. Did you mean 'Date'? -!!! related TS2728 /.ts/lib.es5.d.ts:933:13: 'Date' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:935:13: 'Date' is declared here. d.getXDate(); var n=XDate.parse("3/2/2004"); ~~~~~ !!! error TS2552: Cannot find name 'XDate'. Did you mean 'Date'? -!!! related TS2728 /.ts/lib.es5.d.ts:933:13: 'Date' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:935:13: 'Date' is declared here. n=XDate.UTC(1964,2,1); ~~~~~ !!! error TS2552: Cannot find name 'XDate'. Did you mean 'Date'? -!!! related TS2728 /.ts/lib.es5.d.ts:933:13: 'Date' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:935:13: 'Date' is declared here. \ No newline at end of file diff --git a/tests/baselines/reference/importHelpers.types b/tests/baselines/reference/importHelpers.types index 8c1f87947f7ad..c65135ceb376d 100644 --- a/tests/baselines/reference/importHelpers.types +++ b/tests/baselines/reference/importHelpers.types @@ -31,8 +31,8 @@ function id(x: T) { } export const result = id`hello world`; ->result : TemplateStringsArray ->id`hello world` : TemplateStringsArray +>result : TemplateStringsArrayOf +>id`hello world` : TemplateStringsArrayOf >id : (x: T) => T >`hello world` : "hello world" @@ -69,8 +69,8 @@ function id(x: T) { } const result = id`hello world`; ->result : TemplateStringsArray ->id`hello world` : TemplateStringsArray +>result : TemplateStringsArrayOf +>id`hello world` : TemplateStringsArrayOf >id : (x: T) => T >`hello world` : "hello world" diff --git a/tests/baselines/reference/inferTypes1.errors.txt b/tests/baselines/reference/inferTypes1.errors.txt index 277f3e912d2a3..542ded65d432e 100644 --- a/tests/baselines/reference/inferTypes1.errors.txt +++ b/tests/baselines/reference/inferTypes1.errors.txt @@ -243,4 +243,8 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(153,40): error TS2322: const result = invoker('test', true)({ test: (a: boolean) => 123 }) type Foo2 = ReturnType<(...args: A) => string>; + + // Infer from an intersected tuple + type Head = T extends [infer THead, ...infer _] ? THead : never; + type T100 = Head<["a", "c"] & { foo: "bar" }>; \ No newline at end of file diff --git a/tests/baselines/reference/inferTypes1.js b/tests/baselines/reference/inferTypes1.js index 35421c73ad285..b431288fb20ee 100644 --- a/tests/baselines/reference/inferTypes1.js +++ b/tests/baselines/reference/inferTypes1.js @@ -185,6 +185,10 @@ function invoker (key: K, const result = invoker('test', true)({ test: (a: boolean) => 123 }) type Foo2 = ReturnType<(...args: A) => string>; + +// Infer from an intersected tuple +type Head = T extends [infer THead, ...infer _] ? THead : never; +type T100 = Head<["a", "c"] & { foo: "bar" }>; //// [inferTypes1.js] diff --git a/tests/baselines/reference/inferTypes1.symbols b/tests/baselines/reference/inferTypes1.symbols index 33d8052a8c73e..587b909aaa81d 100644 --- a/tests/baselines/reference/inferTypes1.symbols +++ b/tests/baselines/reference/inferTypes1.symbols @@ -775,3 +775,17 @@ type Foo2 = ReturnType<(...args: A) => string>; >args : Symbol(args, Decl(inferTypes1.ts, 185, 41)) >A : Symbol(A, Decl(inferTypes1.ts, 185, 10)) +// Infer from an intersected tuple +type Head = T extends [infer THead, ...infer _] ? THead : never; +>Head : Symbol(Head, Decl(inferTypes1.ts, 185, 64)) +>T : Symbol(T, Decl(inferTypes1.ts, 188, 10)) +>T : Symbol(T, Decl(inferTypes1.ts, 188, 10)) +>THead : Symbol(THead, Decl(inferTypes1.ts, 188, 48)) +>_ : Symbol(_, Decl(inferTypes1.ts, 188, 64)) +>THead : Symbol(THead, Decl(inferTypes1.ts, 188, 48)) + +type T100 = Head<["a", "c"] & { foo: "bar" }>; +>T100 : Symbol(T100, Decl(inferTypes1.ts, 188, 84)) +>Head : Symbol(Head, Decl(inferTypes1.ts, 185, 64)) +>foo : Symbol(foo, Decl(inferTypes1.ts, 189, 31)) + diff --git a/tests/baselines/reference/inferTypes1.types b/tests/baselines/reference/inferTypes1.types index 964ae6c5c6bcd..e45ceef78e219 100644 --- a/tests/baselines/reference/inferTypes1.types +++ b/tests/baselines/reference/inferTypes1.types @@ -493,3 +493,11 @@ type Foo2 = ReturnType<(...args: A) => string>; >Foo2 : string >args : A +// Infer from an intersected tuple +type Head = T extends [infer THead, ...infer _] ? THead : never; +>Head : Head + +type T100 = Head<["a", "c"] & { foo: "bar" }>; +>T100 : "a" +>foo : "bar" + diff --git a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.errors.txt b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.errors.txt index 1f06530c7be2d..617a512a365bb 100644 --- a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.errors.txt +++ b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.errors.txt @@ -7,5 +7,5 @@ tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty.ts(3,1): error T tgt2 = src2; // Should error ~~~~ !!! error TS2741: Property 'length' is missing in type '{ [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; find: { (predicate: (this: void, value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]; flat: (this: A, depth?: D) => FlatArray[]; [iterator]: () => IterableIterator; [unscopables]: () => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; }' but required in type 'number[]'. -!!! related TS2728 /.ts/lib.es5.d.ts:1279:5: 'length' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1281:5: 'length' is declared here. \ No newline at end of file diff --git a/tests/baselines/reference/narrowExceptionVariableInCatchClause.errors.txt b/tests/baselines/reference/narrowExceptionVariableInCatchClause.errors.txt index 2d961d4fa0a08..d4cb33d3b4418 100644 --- a/tests/baselines/reference/narrowExceptionVariableInCatchClause.errors.txt +++ b/tests/baselines/reference/narrowExceptionVariableInCatchClause.errors.txt @@ -24,7 +24,7 @@ tests/cases/conformance/types/any/narrowExceptionVariableInCatchClause.ts(16,17) err.massage; // ERROR: Property 'massage' does not exist on type 'Error' ~~~~~~~ !!! error TS2551: Property 'massage' does not exist on type 'Error'. Did you mean 'message'? -!!! related TS2728 /.ts/lib.es5.d.ts:1029:5: 'message' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1031:5: 'message' is declared here. } else { diff --git a/tests/baselines/reference/narrowFromAnyWithInstanceof.errors.txt b/tests/baselines/reference/narrowFromAnyWithInstanceof.errors.txt index c32d742cad519..030b8ec4e9a08 100644 --- a/tests/baselines/reference/narrowFromAnyWithInstanceof.errors.txt +++ b/tests/baselines/reference/narrowFromAnyWithInstanceof.errors.txt @@ -22,7 +22,7 @@ tests/cases/conformance/types/any/narrowFromAnyWithInstanceof.ts(22,7): error TS x.mesage; ~~~~~~ !!! error TS2551: Property 'mesage' does not exist on type 'Error'. Did you mean 'message'? -!!! related TS2728 /.ts/lib.es5.d.ts:1029:5: 'message' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1031:5: 'message' is declared here. } if (x instanceof Date) { @@ -30,6 +30,6 @@ tests/cases/conformance/types/any/narrowFromAnyWithInstanceof.ts(22,7): error TS x.getHuors(); ~~~~~~~~ !!! error TS2551: Property 'getHuors' does not exist on type 'Date'. Did you mean 'getHours'? -!!! related TS2728 /.ts/lib.es5.d.ts:789:5: 'getHours' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:791:5: 'getHours' is declared here. } \ No newline at end of file diff --git a/tests/baselines/reference/narrowFromAnyWithTypePredicate.errors.txt b/tests/baselines/reference/narrowFromAnyWithTypePredicate.errors.txt index 232a03f038c17..681dbab746566 100644 --- a/tests/baselines/reference/narrowFromAnyWithTypePredicate.errors.txt +++ b/tests/baselines/reference/narrowFromAnyWithTypePredicate.errors.txt @@ -41,7 +41,7 @@ tests/cases/conformance/types/any/narrowFromAnyWithTypePredicate.ts(33,7): error x.mesage; ~~~~~~ !!! error TS2551: Property 'mesage' does not exist on type 'Error'. Did you mean 'message'? -!!! related TS2728 /.ts/lib.es5.d.ts:1029:5: 'message' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1031:5: 'message' is declared here. } if (isDate(x)) { @@ -49,6 +49,6 @@ tests/cases/conformance/types/any/narrowFromAnyWithTypePredicate.ts(33,7): error x.getHuors(); ~~~~~~~~ !!! error TS2551: Property 'getHuors' does not exist on type 'Date'. Did you mean 'getHours'? -!!! related TS2728 /.ts/lib.es5.d.ts:789:5: 'getHours' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:791:5: 'getHours' is declared here. } \ No newline at end of file diff --git a/tests/baselines/reference/parserS7.2_A1.5_T2.errors.txt b/tests/baselines/reference/parserS7.2_A1.5_T2.errors.txt index cfa2d3c17c5df..4c7ca623f6a88 100644 --- a/tests/baselines/reference/parserS7.2_A1.5_T2.errors.txt +++ b/tests/baselines/reference/parserS7.2_A1.5_T2.errors.txt @@ -19,7 +19,7 @@ tests/cases/conformance/parser/ecmascript5/parserS7.2_A1.5_T2.ts(20,3): error TS $ERROR('#1: eval("\\u00A0var x\\u00A0= 1\\u00A0"); x === 1. Actual: ' + (x)); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } //CHECK#2 @@ -28,7 +28,7 @@ tests/cases/conformance/parser/ecmascript5/parserS7.2_A1.5_T2.ts(20,3): error TS $ERROR('#2:  var x = 1 ; x === 1. Actual: ' + (x)); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } diff --git a/tests/baselines/reference/parserS7.3_A1.1_T2.errors.txt b/tests/baselines/reference/parserS7.3_A1.1_T2.errors.txt index 93c14e1d5f186..5d667fb0d330e 100644 --- a/tests/baselines/reference/parserS7.3_A1.1_T2.errors.txt +++ b/tests/baselines/reference/parserS7.3_A1.1_T2.errors.txt @@ -21,7 +21,7 @@ tests/cases/conformance/parser/ecmascript5/parserS7.3_A1.1_T2.ts(17,3): error TS $ERROR('#1: var\\nx\\n=\\n1\\n; x === 1. Actual: ' + (x)); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } \ No newline at end of file diff --git a/tests/baselines/reference/parserS7.6_A4.2_T1.errors.txt b/tests/baselines/reference/parserS7.6_A4.2_T1.errors.txt index 44e509226b600..0cc77b064c296 100644 --- a/tests/baselines/reference/parserS7.6_A4.2_T1.errors.txt +++ b/tests/baselines/reference/parserS7.6_A4.2_T1.errors.txt @@ -50,70 +50,70 @@ tests/cases/conformance/parser/ecmascript5/parserS7.6_A4.2_T1.ts(142,3): error T $ERROR('#А'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0411 = 1; if (Б !== 1) { $ERROR('#Б'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0412 = 1; if (В !== 1) { $ERROR('#В'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0413 = 1; if (Г !== 1) { $ERROR('#Г'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0414 = 1; if (Д !== 1) { $ERROR('#Д'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0415 = 1; if (Е !== 1) { $ERROR('#Е'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0416 = 1; if (Ж !== 1) { $ERROR('#Ж'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0417 = 1; if (З !== 1) { $ERROR('#З'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0418 = 1; if (И !== 1) { $ERROR('#И'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0419 = 1; if (Й !== 1) { $ERROR('#Й'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u041A = 1; if (К !== 1) { diff --git a/tests/baselines/reference/parserUnicode1.errors.txt b/tests/baselines/reference/parserUnicode1.errors.txt index 381f7757a97dc..673bbe03ae1fc 100644 --- a/tests/baselines/reference/parserUnicode1.errors.txt +++ b/tests/baselines/reference/parserUnicode1.errors.txt @@ -11,13 +11,13 @@ tests/cases/conformance/parser/ecmascript5/parserUnicode1.ts(10,5): error TS2552 $ERROR('#6.1: var \\u0078x = 1; xx === 6. Actual: ' + (xx)); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } } catch (e) { $ERROR('#6.2: var \\u0078x = 1; xx === 6. Actual: ' + (xx)); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } \ No newline at end of file diff --git a/tests/baselines/reference/promisePermutations.errors.txt b/tests/baselines/reference/promisePermutations.errors.txt index e031002905c3d..ab38a9eb136c0 100644 --- a/tests/baselines/reference/promisePermutations.errors.txt +++ b/tests/baselines/reference/promisePermutations.errors.txt @@ -447,7 +447,7 @@ tests/cases/compiler/promisePermutations.ts(160,21): error TS2769: No overload m !!! error TS2769: The last overload gave the following error. !!! error TS2769: Argument of type '(x: any) => IPromise' is not assignable to parameter of type '(error: any) => Promise'. !!! error TS2769: Property 'catch' is missing in type 'IPromise' but required in type 'Promise'. -!!! related TS2728 /.ts/lib.es5.d.ts:1515:5: 'catch' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1517:5: 'catch' is declared here. !!! related TS2771 tests/cases/compiler/promisePermutations.ts:5:5: The last overload is declared here. var s10g = s10.then(testFunctionP, nIPromise, sIPromise).then(sPromise, sIPromise, sIPromise); // ok diff --git a/tests/baselines/reference/promisePermutations2.errors.txt b/tests/baselines/reference/promisePermutations2.errors.txt index c6b8f3d344504..1f70a20da1e04 100644 --- a/tests/baselines/reference/promisePermutations2.errors.txt +++ b/tests/baselines/reference/promisePermutations2.errors.txt @@ -351,7 +351,7 @@ tests/cases/compiler/promisePermutations2.ts(159,21): error TS2345: Argument of ~~~~~~~~~ !!! error TS2345: Argument of type '(x: any) => IPromise' is not assignable to parameter of type '(error: any) => Promise'. !!! error TS2345: Property 'catch' is missing in type 'IPromise' but required in type 'Promise'. -!!! related TS2728 /.ts/lib.es5.d.ts:1515:5: 'catch' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1517:5: 'catch' is declared here. var s10g = s10.then(testFunctionP, nIPromise, sIPromise).then(sPromise, sIPromise, sIPromise); // ok var r11: IPromise; diff --git a/tests/baselines/reference/promisePermutations3.errors.txt b/tests/baselines/reference/promisePermutations3.errors.txt index 7cbd6bafe458c..8564120cf8cef 100644 --- a/tests/baselines/reference/promisePermutations3.errors.txt +++ b/tests/baselines/reference/promisePermutations3.errors.txt @@ -398,7 +398,7 @@ tests/cases/compiler/promisePermutations3.ts(165,21): error TS2345: Argument of !!! error TS2769: The last overload gave the following error. !!! error TS2769: Argument of type '(x: any) => IPromise' is not assignable to parameter of type '(error: any) => Promise'. !!! error TS2769: Property 'catch' is missing in type 'IPromise' but required in type 'Promise'. -!!! related TS2728 /.ts/lib.es5.d.ts:1515:5: 'catch' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1517:5: 'catch' is declared here. !!! related TS2771 tests/cases/compiler/promisePermutations3.ts:7:5: The last overload is declared here. var s10g = s10.then(testFunctionP, nIPromise, sIPromise).then(sPromise, sIPromise, sIPromise); // ok @@ -445,5 +445,5 @@ tests/cases/compiler/promisePermutations3.ts(165,21): error TS2345: Argument of ~~~~~~~~~~~~~~~ !!! error TS2345: Argument of type '{ (x: T): IPromise; (x: T, y: T): Promise; }' is not assignable to parameter of type '(value: (x: any) => any) => Promise'. !!! error TS2345: Property 'catch' is missing in type 'IPromise' but required in type 'Promise'. -!!! related TS2728 /.ts/lib.es5.d.ts:1515:5: 'catch' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1517:5: 'catch' is declared here. var s12c = s12.then(testFunction12P, testFunction12, testFunction12); // ok \ No newline at end of file diff --git a/tests/baselines/reference/redefineArray.errors.txt b/tests/baselines/reference/redefineArray.errors.txt index a03a0ba769a9a..93f39ad543cb9 100644 --- a/tests/baselines/reference/redefineArray.errors.txt +++ b/tests/baselines/reference/redefineArray.errors.txt @@ -5,4 +5,4 @@ tests/cases/compiler/redefineArray.ts(1,1): error TS2741: Property 'isArray' is Array = function (n:number, s:string) {return n;}; ~~~~~ !!! error TS2741: Property 'isArray' is missing in type '(n: number, s: string) => number' but required in type 'ArrayConstructor'. -!!! related TS2728 /.ts/lib.es5.d.ts:1466:5: 'isArray' is declared here. \ No newline at end of file +!!! related TS2728 /.ts/lib.es5.d.ts:1468:5: 'isArray' is declared here. \ No newline at end of file diff --git a/tests/baselines/reference/scannerS7.2_A1.5_T2.errors.txt b/tests/baselines/reference/scannerS7.2_A1.5_T2.errors.txt index ba3fd00347cb5..b5531a521e75b 100644 --- a/tests/baselines/reference/scannerS7.2_A1.5_T2.errors.txt +++ b/tests/baselines/reference/scannerS7.2_A1.5_T2.errors.txt @@ -19,7 +19,7 @@ tests/cases/conformance/scanner/ecmascript5/scannerS7.2_A1.5_T2.ts(20,3): error $ERROR('#1: eval("\\u00A0var x\\u00A0= 1\\u00A0"); x === 1. Actual: ' + (x)); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } //CHECK#2 @@ -28,7 +28,7 @@ tests/cases/conformance/scanner/ecmascript5/scannerS7.2_A1.5_T2.ts(20,3): error $ERROR('#2:  var x = 1 ; x === 1. Actual: ' + (x)); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } diff --git a/tests/baselines/reference/scannerS7.3_A1.1_T2.errors.txt b/tests/baselines/reference/scannerS7.3_A1.1_T2.errors.txt index 5bcb335797a16..71060bb01c68e 100644 --- a/tests/baselines/reference/scannerS7.3_A1.1_T2.errors.txt +++ b/tests/baselines/reference/scannerS7.3_A1.1_T2.errors.txt @@ -21,7 +21,7 @@ tests/cases/conformance/scanner/ecmascript5/scannerS7.3_A1.1_T2.ts(17,3): error $ERROR('#1: var\\nx\\n=\\n1\\n; x === 1. Actual: ' + (x)); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } \ No newline at end of file diff --git a/tests/baselines/reference/scannerS7.6_A4.2_T1.errors.txt b/tests/baselines/reference/scannerS7.6_A4.2_T1.errors.txt index b67a90487044d..b191c3bffed18 100644 --- a/tests/baselines/reference/scannerS7.6_A4.2_T1.errors.txt +++ b/tests/baselines/reference/scannerS7.6_A4.2_T1.errors.txt @@ -50,70 +50,70 @@ tests/cases/conformance/scanner/ecmascript5/scannerS7.6_A4.2_T1.ts(142,3): error $ERROR('#А'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0411 = 1; if (Б !== 1) { $ERROR('#Б'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0412 = 1; if (В !== 1) { $ERROR('#В'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0413 = 1; if (Г !== 1) { $ERROR('#Г'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0414 = 1; if (Д !== 1) { $ERROR('#Д'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0415 = 1; if (Е !== 1) { $ERROR('#Е'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0416 = 1; if (Ж !== 1) { $ERROR('#Ж'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0417 = 1; if (З !== 1) { $ERROR('#З'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0418 = 1; if (И !== 1) { $ERROR('#И'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u0419 = 1; if (Й !== 1) { $ERROR('#Й'); ~~~~~~ !!! error TS2552: Cannot find name '$ERROR'. Did you mean 'Error'? -!!! related TS2728 /.ts/lib.es5.d.ts:1039:13: 'Error' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1041:13: 'Error' is declared here. } var \u041A = 1; if (К !== 1) { diff --git a/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols b/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols new file mode 100644 index 0000000000000..f2c98d3cbcacb --- /dev/null +++ b/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols @@ -0,0 +1,160 @@ +=== tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts === +// overload resolution +declare function f1(array: TemplateStringsArrayOf, ...args: any): "A"; +>f1 : Symbol(f1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 0, 0), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 1, 99), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 2, 99)) +>array : Symbol(array, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 1, 20)) +>TemplateStringsArrayOf : Symbol(TemplateStringsArrayOf, Decl(lib.es5.d.ts, --, --)) +>args : Symbol(args, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 1, 79)) + +declare function f1(array: TemplateStringsArrayOf, ...args: any): "B"; +>f1 : Symbol(f1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 0, 0), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 1, 99), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 2, 99)) +>array : Symbol(array, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 2, 20)) +>TemplateStringsArrayOf : Symbol(TemplateStringsArrayOf, Decl(lib.es5.d.ts, --, --)) +>args : Symbol(args, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 2, 79)) + +declare function f1(array: TemplateStringsArray, ...args: any): "C"; +>f1 : Symbol(f1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 0, 0), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 1, 99), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 2, 99)) +>array : Symbol(array, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 3, 20)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>args : Symbol(args, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 3, 48)) + +const f1_r0 = f1`a`; // "A" +>f1_r0 : Symbol(f1_r0, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 4, 5)) +>f1 : Symbol(f1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 0, 0), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 1, 99), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 2, 99)) + +const f1_r1 = f1`a${"b"}`; // "A" +>f1_r1 : Symbol(f1_r1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 5, 5)) +>f1 : Symbol(f1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 0, 0), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 1, 99), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 2, 99)) + +const f1_r2 = f1`b`; // "B" +>f1_r2 : Symbol(f1_r2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 6, 5)) +>f1 : Symbol(f1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 0, 0), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 1, 99), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 2, 99)) + +const f1_r3 = f1`b${"b"}`; // "B" +>f1_r3 : Symbol(f1_r3, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 7, 5)) +>f1 : Symbol(f1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 0, 0), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 1, 99), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 2, 99)) + +const f1_r4 = f1`c`; // "C" +>f1_r4 : Symbol(f1_r4, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 8, 5)) +>f1 : Symbol(f1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 0, 0), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 1, 99), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 2, 99)) + +const f1_r5 = f1`c${"b"}`; // "C" +>f1_r5 : Symbol(f1_r5, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 9, 5)) +>f1 : Symbol(f1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 0, 0), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 1, 99), Decl(taggedTemplateWithSpecificTemplateStrings.ts, 2, 99)) + +// constrained type parameter +declare function f0(array: T, ...args: A): [T, A]; +>f0 : Symbol(f0, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 9, 26)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 12, 20)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 12, 51)) +>array : Symbol(array, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 12, 72)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 12, 20)) +>args : Symbol(args, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 12, 81)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 12, 51)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 12, 20)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 12, 51)) + +const f0_r0 = f0`a${"b"}c`; // [TemplateStringsArrayOf, ["b"]] +>f0_r0 : Symbol(f0_r0, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 13, 5)) +>f0 : Symbol(f0, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 9, 26)) + +// interpolation example +type TemplatePrimitive = string | number | bigint | boolean | null | undefined; +>TemplatePrimitive : Symbol(TemplatePrimitive, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 13, 27)) + +type Interpolate = +>Interpolate : Symbol(Interpolate, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 16, 79)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 18, 17)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 18, 45)) +>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 18, 62)) + + T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ? +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 18, 17)) +>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 19, 29)) +>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 19, 57)) + + A extends [infer AH extends TemplatePrimitive, ...infer AT extends TemplatePrimitive[]] ? +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 18, 45)) +>AH : Symbol(AH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 20, 24)) +>TemplatePrimitive : Symbol(TemplatePrimitive, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 13, 27)) +>AT : Symbol(AT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 20, 63)) +>TemplatePrimitive : Symbol(TemplatePrimitive, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 13, 27)) + + Interpolate : +>Interpolate : Symbol(Interpolate, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 16, 79)) +>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 19, 57)) +>AT : Symbol(AT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 20, 63)) +>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 18, 62)) +>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 19, 29)) +>AH : Symbol(AH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 20, 24)) + + Interpolate : +>Interpolate : Symbol(Interpolate, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 16, 79)) +>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 19, 57)) +>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 18, 62)) +>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 19, 29)) + + R; +>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 18, 62)) + +// string interpolation +declare function interp(array: T, ...args: A): Interpolate; +>interp : Symbol(interp, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 23, 10)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 26, 24)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 26, 55)) +>TemplatePrimitive : Symbol(TemplatePrimitive, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 13, 27)) +>array : Symbol(array, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 26, 87)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 26, 24)) +>args : Symbol(args, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 26, 96)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 26, 55)) +>Interpolate : Symbol(Interpolate, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 16, 79)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 26, 24)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 26, 55)) + +const interp_r0 = interp`a${"b"}c`; // "abc" +>interp_r0 : Symbol(interp_r0, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 27, 5)) +>interp : Symbol(interp, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 23, 10)) + +const interp_r1 = interp`a${1}c`; // "a1c" +>interp_r1 : Symbol(interp_r1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 28, 5)) +>interp : Symbol(interp, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 23, 10)) + +// "a\nb\nc" +const interp_r2 = interp`a\n${"b"} +>interp_r2 : Symbol(interp_r2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 31, 5)) +>interp : Symbol(interp, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 23, 10)) + +c`; + +// raw string interpolation (i.e., 'String.raw') +declare function raw(array: T, ...args: A): Interpolate; +>raw : Symbol(raw, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 32, 3)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 35, 21)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 35, 52)) +>TemplatePrimitive : Symbol(TemplatePrimitive, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 13, 27)) +>array : Symbol(array, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 35, 84)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 35, 21)) +>args : Symbol(args, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 35, 93)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 35, 52)) +>Interpolate : Symbol(Interpolate, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 16, 79)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 35, 21)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 35, 52)) + +const raw_r0 = raw`a${"b"}c`; // "abc" +>raw_r0 : Symbol(raw_r0, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 36, 5)) +>raw : Symbol(raw, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 32, 3)) + +const raw_r1 = raw`a${1}c`; // "a1c" +>raw_r1 : Symbol(raw_r1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 37, 5)) +>raw : Symbol(raw, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 32, 3)) + +// "a\\nb\nc" +const raw_r2 = raw`a\n${"b"} +>raw_r2 : Symbol(raw_r2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 40, 5)) +>raw : Symbol(raw, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 32, 3)) + +c`; + diff --git a/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types b/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types new file mode 100644 index 0000000000000..40bf04b26567b --- /dev/null +++ b/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types @@ -0,0 +1,143 @@ +=== tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts === +// overload resolution +declare function f1(array: TemplateStringsArrayOf, ...args: any): "A"; +>f1 : { (array: TemplateStringsArrayOf, ...args: any): "A"; (array: TemplateStringsArrayOf, ...args: any): "B"; (array: TemplateStringsArray, ...args: any): "C"; } +>array : TemplateStringsArrayOf +>args : any + +declare function f1(array: TemplateStringsArrayOf, ...args: any): "B"; +>f1 : { (array: TemplateStringsArrayOf, ...args: any): "A"; (array: TemplateStringsArrayOf, ...args: any): "B"; (array: TemplateStringsArray, ...args: any): "C"; } +>array : TemplateStringsArrayOf +>args : any + +declare function f1(array: TemplateStringsArray, ...args: any): "C"; +>f1 : { (array: TemplateStringsArrayOf, ...args: any): "A"; (array: TemplateStringsArrayOf, ...args: any): "B"; (array: TemplateStringsArray, ...args: any): "C"; } +>array : TemplateStringsArray +>args : any + +const f1_r0 = f1`a`; // "A" +>f1_r0 : "A" +>f1`a` : "A" +>f1 : { (array: TemplateStringsArrayOf, ...args: any): "A"; (array: TemplateStringsArrayOf, ...args: any): "B"; (array: TemplateStringsArray, ...args: any): "C"; } +>`a` : "a" + +const f1_r1 = f1`a${"b"}`; // "A" +>f1_r1 : "A" +>f1`a${"b"}` : "A" +>f1 : { (array: TemplateStringsArrayOf, ...args: any): "A"; (array: TemplateStringsArrayOf, ...args: any): "B"; (array: TemplateStringsArray, ...args: any): "C"; } +>`a${"b"}` : string +>"b" : "b" + +const f1_r2 = f1`b`; // "B" +>f1_r2 : "B" +>f1`b` : "B" +>f1 : { (array: TemplateStringsArrayOf, ...args: any): "A"; (array: TemplateStringsArrayOf, ...args: any): "B"; (array: TemplateStringsArray, ...args: any): "C"; } +>`b` : "b" + +const f1_r3 = f1`b${"b"}`; // "B" +>f1_r3 : "B" +>f1`b${"b"}` : "B" +>f1 : { (array: TemplateStringsArrayOf, ...args: any): "A"; (array: TemplateStringsArrayOf, ...args: any): "B"; (array: TemplateStringsArray, ...args: any): "C"; } +>`b${"b"}` : string +>"b" : "b" + +const f1_r4 = f1`c`; // "C" +>f1_r4 : "C" +>f1`c` : "C" +>f1 : { (array: TemplateStringsArrayOf, ...args: any): "A"; (array: TemplateStringsArrayOf, ...args: any): "B"; (array: TemplateStringsArray, ...args: any): "C"; } +>`c` : "c" + +const f1_r5 = f1`c${"b"}`; // "C" +>f1_r5 : "C" +>f1`c${"b"}` : "C" +>f1 : { (array: TemplateStringsArrayOf, ...args: any): "A"; (array: TemplateStringsArrayOf, ...args: any): "B"; (array: TemplateStringsArray, ...args: any): "C"; } +>`c${"b"}` : string +>"b" : "b" + +// constrained type parameter +declare function f0(array: T, ...args: A): [T, A]; +>f0 : (array: T, ...args: A) => [T, A] +>array : T +>args : A + +const f0_r0 = f0`a${"b"}c`; // [TemplateStringsArrayOf, ["b"]] +>f0_r0 : [TemplateStringsArrayOf, ["b"]] +>f0`a${"b"}c` : [TemplateStringsArrayOf, ["b"]] +>f0 : (array: T, ...args: A) => [T, A] +>`a${"b"}c` : string +>"b" : "b" + +// interpolation example +type TemplatePrimitive = string | number | bigint | boolean | null | undefined; +>TemplatePrimitive : string | number | bigint | boolean +>null : null + +type Interpolate = +>Interpolate : Interpolate + + T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ? + A extends [infer AH extends TemplatePrimitive, ...infer AT extends TemplatePrimitive[]] ? + Interpolate : + Interpolate : + R; + +// string interpolation +declare function interp(array: T, ...args: A): Interpolate; +>interp : (array: T, ...args: A) => Interpolate +>array : T +>args : A + +const interp_r0 = interp`a${"b"}c`; // "abc" +>interp_r0 : "abc" +>interp`a${"b"}c` : "abc" +>interp : (array: T, ...args: A) => Interpolate +>`a${"b"}c` : string +>"b" : "b" + +const interp_r1 = interp`a${1}c`; // "a1c" +>interp_r1 : "a1c" +>interp`a${1}c` : "a1c" +>interp : (array: T, ...args: A) => Interpolate +>`a${1}c` : string +>1 : 1 + +// "a\nb\nc" +const interp_r2 = interp`a\n${"b"} +>interp_r2 : "a\nb\nc" +>interp`a\n${"b"}c` : "a\nb\nc" +>interp : (array: T, ...args: A) => Interpolate +>`a\n${"b"}c` : string +>"b" : "b" + +c`; + +// raw string interpolation (i.e., 'String.raw') +declare function raw(array: T, ...args: A): Interpolate; +>raw : (array: T, ...args: A) => Interpolate +>array : T +>args : A + +const raw_r0 = raw`a${"b"}c`; // "abc" +>raw_r0 : "abc" +>raw`a${"b"}c` : "abc" +>raw : (array: T, ...args: A) => Interpolate +>`a${"b"}c` : string +>"b" : "b" + +const raw_r1 = raw`a${1}c`; // "a1c" +>raw_r1 : "a1c" +>raw`a${1}c` : "a1c" +>raw : (array: T, ...args: A) => Interpolate +>`a${1}c` : string +>1 : 1 + +// "a\\nb\nc" +const raw_r2 = raw`a\n${"b"} +>raw_r2 : "a\\nb\nc" +>raw`a\n${"b"}c` : "a\\nb\nc" +>raw : (array: T, ...args: A) => Interpolate +>`a\n${"b"}c` : string +>"b" : "b" + +c`; + diff --git a/tests/baselines/reference/taggedTemplateWithoutDeclaredHelper.types b/tests/baselines/reference/taggedTemplateWithoutDeclaredHelper.types index aef2556181a15..e0e07e7f6e5b3 100644 --- a/tests/baselines/reference/taggedTemplateWithoutDeclaredHelper.types +++ b/tests/baselines/reference/taggedTemplateWithoutDeclaredHelper.types @@ -8,8 +8,8 @@ function id(x: T) { } export const result = id `hello world`; ->result : TemplateStringsArray ->id `hello world` : TemplateStringsArray +>result : TemplateStringsArrayOf +>id `hello world` : TemplateStringsArrayOf >id : (x: T) => T >`hello world` : "hello world" diff --git a/tests/baselines/reference/taggedTemplatesInModuleAndGlobal.types b/tests/baselines/reference/taggedTemplatesInModuleAndGlobal.types index e08b5f3afa876..47989f50a9eed 100644 --- a/tests/baselines/reference/taggedTemplatesInModuleAndGlobal.types +++ b/tests/baselines/reference/taggedTemplatesInModuleAndGlobal.types @@ -11,20 +11,20 @@ namespace n { } function templateObjectFactory() { ->templateObjectFactory : () => TemplateStringsArray +>templateObjectFactory : () => TemplateStringsArrayOf return id`hello world`; ->id`hello world` : TemplateStringsArray +>id`hello world` : TemplateStringsArrayOf >id : (x: T) => T >`hello world` : "hello world" } let result = templateObjectFactory() === templateObjectFactory(); >result : boolean >templateObjectFactory() === templateObjectFactory() : boolean ->templateObjectFactory() : TemplateStringsArray ->templateObjectFactory : () => TemplateStringsArray ->templateObjectFactory() : TemplateStringsArray ->templateObjectFactory : () => TemplateStringsArray +>templateObjectFactory() : TemplateStringsArrayOf +>templateObjectFactory : () => TemplateStringsArrayOf +>templateObjectFactory() : TemplateStringsArrayOf +>templateObjectFactory : () => TemplateStringsArrayOf } === tests/cases/compiler/module.ts === export { } @@ -37,18 +37,18 @@ function id(x: T): T { } function templateObjectFactory() { ->templateObjectFactory : () => TemplateStringsArray +>templateObjectFactory : () => TemplateStringsArrayOf return id`hello world`; ->id`hello world` : TemplateStringsArray +>id`hello world` : TemplateStringsArrayOf >id : (x: T) => T >`hello world` : "hello world" } let result = templateObjectFactory() === templateObjectFactory(); >result : boolean >templateObjectFactory() === templateObjectFactory() : boolean ->templateObjectFactory() : TemplateStringsArray ->templateObjectFactory : () => TemplateStringsArray ->templateObjectFactory() : TemplateStringsArray ->templateObjectFactory : () => TemplateStringsArray +>templateObjectFactory() : TemplateStringsArrayOf +>templateObjectFactory : () => TemplateStringsArrayOf +>templateObjectFactory() : TemplateStringsArrayOf +>templateObjectFactory : () => TemplateStringsArrayOf diff --git a/tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts b/tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts new file mode 100644 index 0000000000000..402887f4cf37e --- /dev/null +++ b/tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts @@ -0,0 +1,45 @@ +// @target: esnext +// @noEmit: true + +// overload resolution +declare function f1(array: TemplateStringsArrayOf, ...args: any): "A"; +declare function f1(array: TemplateStringsArrayOf, ...args: any): "B"; +declare function f1(array: TemplateStringsArray, ...args: any): "C"; +const f1_r0 = f1`a`; // "A" +const f1_r1 = f1`a${"b"}`; // "A" +const f1_r2 = f1`b`; // "B" +const f1_r3 = f1`b${"b"}`; // "B" +const f1_r4 = f1`c`; // "C" +const f1_r5 = f1`c${"b"}`; // "C" + +// constrained type parameter +declare function f0(array: T, ...args: A): [T, A]; +const f0_r0 = f0`a${"b"}c`; // [TemplateStringsArrayOf, ["b"]] + +// interpolation example +type TemplatePrimitive = string | number | bigint | boolean | null | undefined; + +type Interpolate = + T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ? + A extends [infer AH extends TemplatePrimitive, ...infer AT extends TemplatePrimitive[]] ? + Interpolate : + Interpolate : + R; + +// string interpolation +declare function interp(array: T, ...args: A): Interpolate; +const interp_r0 = interp`a${"b"}c`; // "abc" +const interp_r1 = interp`a${1}c`; // "a1c" + +// "a\nb\nc" +const interp_r2 = interp`a\n${"b"} +c`; + +// raw string interpolation (i.e., 'String.raw') +declare function raw(array: T, ...args: A): Interpolate; +const raw_r0 = raw`a${"b"}c`; // "abc" +const raw_r1 = raw`a${1}c`; // "a1c" + +// "a\\nb\nc" +const raw_r2 = raw`a\n${"b"} +c`; diff --git a/tests/cases/conformance/types/conditional/inferTypes1.ts b/tests/cases/conformance/types/conditional/inferTypes1.ts index 42e5897dc663f..b7dc9dcb4180d 100644 --- a/tests/cases/conformance/types/conditional/inferTypes1.ts +++ b/tests/cases/conformance/types/conditional/inferTypes1.ts @@ -187,3 +187,7 @@ function invoker (key: K, const result = invoker('test', true)({ test: (a: boolean) => 123 }) type Foo2 = ReturnType<(...args: A) => string>; + +// Infer from an intersected tuple +type Head = T extends [infer THead, ...infer _] ? THead : never; +type T100 = Head<["a", "c"] & { foo: "bar" }>; From f8752ad296573db618861f4c4b75b60682bee682 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 16 Jun 2022 16:58:24 -0700 Subject: [PATCH 2/3] Remove order dependence and add test showing use case for Jest's 'each' --- src/compiler/checker.ts | 4 + .../reference/inferTypes1.errors.txt | 3 +- tests/baselines/reference/inferTypes1.js | 3 +- tests/baselines/reference/inferTypes1.symbols | 6 +- tests/baselines/reference/inferTypes1.types | 5 +- ...emplateWithSpecificTemplateStrings.symbols | 187 ++++++++++++++++++ ...dTemplateWithSpecificTemplateStrings.types | 88 ++++++++- ...ggedTemplateWithSpecificTemplateStrings.ts | 47 +++++ .../types/conditional/inferTypes1.ts | 3 +- 9 files changed, 340 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6f190bf74c64d..973d4271e2511 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21195,6 +21195,10 @@ namespace ts { let arrayOrTupleConstituent: TypeReference | undefined; for (const constituent of (type as IntersectionType).types) { if (isArrayOrTupleType(constituent)) { + // If this is an intersection of two array or tuple types, prefer neither. + if (arrayOrTupleConstituent) { + return undefined; + } arrayOrTupleConstituent = constituent; } else { diff --git a/tests/baselines/reference/inferTypes1.errors.txt b/tests/baselines/reference/inferTypes1.errors.txt index 542ded65d432e..cec8eaea55cf0 100644 --- a/tests/baselines/reference/inferTypes1.errors.txt +++ b/tests/baselines/reference/inferTypes1.errors.txt @@ -246,5 +246,6 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(153,40): error TS2322: // Infer from an intersected tuple type Head = T extends [infer THead, ...infer _] ? THead : never; - type T100 = Head<["a", "c"] & { foo: "bar" }>; + type T100 = Head<["a", "c"] & { foo: "bar" }>; // "a" + type T101 = Head<["a", "c"] & readonly ["a", "c"]>; // "a" | "c" \ No newline at end of file diff --git a/tests/baselines/reference/inferTypes1.js b/tests/baselines/reference/inferTypes1.js index b431288fb20ee..67ab98f9b31b9 100644 --- a/tests/baselines/reference/inferTypes1.js +++ b/tests/baselines/reference/inferTypes1.js @@ -188,7 +188,8 @@ type Foo2 = ReturnType<(...args: A) => string>; // Infer from an intersected tuple type Head = T extends [infer THead, ...infer _] ? THead : never; -type T100 = Head<["a", "c"] & { foo: "bar" }>; +type T100 = Head<["a", "c"] & { foo: "bar" }>; // "a" +type T101 = Head<["a", "c"] & readonly ["a", "c"]>; // "a" | "c" //// [inferTypes1.js] diff --git a/tests/baselines/reference/inferTypes1.symbols b/tests/baselines/reference/inferTypes1.symbols index 587b909aaa81d..d4b35b39a1a00 100644 --- a/tests/baselines/reference/inferTypes1.symbols +++ b/tests/baselines/reference/inferTypes1.symbols @@ -784,8 +784,12 @@ type Head = T extends [infer THead, ...infer _] ? THead : ne >_ : Symbol(_, Decl(inferTypes1.ts, 188, 64)) >THead : Symbol(THead, Decl(inferTypes1.ts, 188, 48)) -type T100 = Head<["a", "c"] & { foo: "bar" }>; +type T100 = Head<["a", "c"] & { foo: "bar" }>; // "a" >T100 : Symbol(T100, Decl(inferTypes1.ts, 188, 84)) >Head : Symbol(Head, Decl(inferTypes1.ts, 185, 64)) >foo : Symbol(foo, Decl(inferTypes1.ts, 189, 31)) +type T101 = Head<["a", "c"] & readonly ["a", "c"]>; // "a" | "c" +>T101 : Symbol(T101, Decl(inferTypes1.ts, 189, 46)) +>Head : Symbol(Head, Decl(inferTypes1.ts, 185, 64)) + diff --git a/tests/baselines/reference/inferTypes1.types b/tests/baselines/reference/inferTypes1.types index e45ceef78e219..84f1a26d7ca3b 100644 --- a/tests/baselines/reference/inferTypes1.types +++ b/tests/baselines/reference/inferTypes1.types @@ -497,7 +497,10 @@ type Foo2 = ReturnType<(...args: A) => string>; type Head = T extends [infer THead, ...infer _] ? THead : never; >Head : Head -type T100 = Head<["a", "c"] & { foo: "bar" }>; +type T100 = Head<["a", "c"] & { foo: "bar" }>; // "a" >T100 : "a" >foo : "bar" +type T101 = Head<["a", "c"] & readonly ["a", "c"]>; // "a" | "c" +>T101 : "a" | "c" + diff --git a/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols b/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols index f2c98d3cbcacb..b4cf753143775 100644 --- a/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols +++ b/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols @@ -158,3 +158,190 @@ const raw_r2 = raw`a\n${"b"} c`; +// Jest's `it.each`: +type Whitespace = " " | "\t" | "\v" +>Whitespace : Symbol(Whitespace, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 41, 3)) + +type Trim = +>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35)) +>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 10)) +>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27)) +>Whitespace : Symbol(Whitespace, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 41, 3)) + + S extends `${Chars}${infer R}` ? Trim : +>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 10)) +>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27)) +>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 47, 30)) +>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35)) +>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 47, 30)) +>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27)) + + S extends `${infer R}${Chars}` ? Trim : +>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 10)) +>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 48, 22)) +>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27)) +>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35)) +>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 48, 22)) +>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27)) + + S; +>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 10)) + +type Split = +>Split : Symbol(Split, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 49, 6)) +>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 11)) +>D : Symbol(D, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 28)) + + S extends D ? [] : +>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 11)) +>D : Symbol(D, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 28)) + + S extends `${infer H}${D}${infer T}` ? [H, ...Split] : +>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 11)) +>H : Symbol(H, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 53, 22)) +>D : Symbol(D, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 28)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 53, 36)) +>H : Symbol(H, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 53, 22)) +>Split : Symbol(Split, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 49, 6)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 53, 36)) +>D : Symbol(D, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 28)) + + [S]; +>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 11)) + +type ParseRows = +>ParseRows : Symbol(ParseRows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 54, 8)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 15)) +>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 31)) +>Row : Symbol(Row, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 60)) +>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 84)) + + [A, S] extends [[infer AH, ...infer AT], readonly [infer TH extends string, ...infer TT extends string[]]] ? +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 15)) +>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 31)) +>AH : Symbol(AH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 26)) +>AT : Symbol(AT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 39)) +>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 60)) +>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 88)) + + Trim extends "|" ? ParseRows : +>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35)) +>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 60)) +>Whitespace : Symbol(Whitespace, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 41, 3)) +>ParseRows : Symbol(ParseRows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 54, 8)) +>AT : Symbol(AT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 39)) +>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 88)) +>Row : Symbol(Row, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 60)) +>AH : Symbol(AH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 26)) +>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 84)) + + Trim extends "\n" | "" ? ParseRows : +>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35)) +>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 60)) +>Whitespace : Symbol(Whitespace, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 41, 3)) +>ParseRows : Symbol(ParseRows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 54, 8)) +>AT : Symbol(AT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 39)) +>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 88)) +>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 84)) +>Row : Symbol(Row, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 60)) +>AH : Symbol(AH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 26)) + + never : + [A, S] extends [[], readonly []] ? Rows : +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 15)) +>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 31)) +>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 84)) + + never; + +type JestEachArgument = { +>JestEachArgument : Symbol(JestEachArgument, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 62, 10)) +>Headers : Symbol(Headers, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 22)) +>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 47)) + + [P1 in keyof Rows]: { +>P1 : Symbol(P1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 65, 5)) +>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 47)) + + [P2 in keyof Headers as P2 extends `${number}` ? Trim : never]: +>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9)) +>Headers : Symbol(Headers, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 22)) +>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9)) +>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35)) +>Headers : Symbol(Headers, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 22)) +>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9)) + + P2 extends keyof Rows[P1] ? Rows[P1][P2] : undefined; +>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9)) +>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 47)) +>P1 : Symbol(P1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 65, 5)) +>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 47)) +>P1 : Symbol(P1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 65, 5)) +>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9)) + + }; +}[number]; + +type JestEachFunction = (name: string, cb: (arg: Arg) => void, timeout?: number) => void; +>JestEachFunction : Symbol(JestEachFunction, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 69, 10)) +>Arg : Symbol(Arg, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 22)) +>name : Symbol(name, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 30)) +>cb : Symbol(cb, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 43)) +>arg : Symbol(arg, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 49)) +>Arg : Symbol(Arg, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 22)) +>timeout : Symbol(timeout, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 67)) + +type JestEach = +>JestEach : Symbol(JestEach, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 94)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 73, 14)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 73, 42)) + + T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ? +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 73, 14)) +>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 74, 29)) +>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 74, 57)) + + JestEachFunction, "|">, ParseRows>> : +>JestEachFunction : Symbol(JestEachFunction, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 69, 10)) +>JestEachArgument : Symbol(JestEachArgument, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 62, 10)) +>Split : Symbol(Split, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 49, 6)) +>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35)) +>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 74, 29)) +>ParseRows : Symbol(ParseRows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 54, 8)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 73, 42)) +>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 74, 57)) + + null; + +declare function each(strs: T, ...args: A): JestEach; +>each : Symbol(each, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 76, 13)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 22)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 50)) +>strs : Symbol(strs, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 72)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 22)) +>args : Symbol(args, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 80)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 50)) +>JestEach : Symbol(JestEach, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 94)) +>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 22)) +>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 50)) + +each` +>each : Symbol(each, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 76, 13)) + + foo | bar + ${"a"} | ${1} + ${"c"} | ${undefined} +>undefined : Symbol(undefined) + +`("test", ({ foo, bar }) => { +>foo : Symbol(foo, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 84, 12)) +>bar : Symbol(bar, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 84, 17)) + + foo; +>foo : Symbol(foo, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 84, 12)) + + bar; +>bar : Symbol(bar, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 84, 17)) + +}); + diff --git a/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types b/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types index 40bf04b26567b..3d3d6804e1c2f 100644 --- a/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types +++ b/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types @@ -69,7 +69,7 @@ const f0_r0 = f0`a${"b"}c`; // [TemplateStringsArrayOfTemplatePrimitive : string | number | bigint | boolean +>TemplatePrimitive : string | number | bigint | boolean | null | undefined >null : null type Interpolate = @@ -141,3 +141,89 @@ const raw_r2 = raw`a\n${"b"} c`; +// Jest's `it.each`: +type Whitespace = " " | "\t" | "\v" +>Whitespace : " " | "\t" | "\v" + +type Trim = +>Trim : Trim + + S extends `${Chars}${infer R}` ? Trim : + S extends `${infer R}${Chars}` ? Trim : + S; + +type Split = +>Split : Split + + S extends D ? [] : + S extends `${infer H}${D}${infer T}` ? [H, ...Split] : + [S]; + +type ParseRows = +>ParseRows : ParseRows + + [A, S] extends [[infer AH, ...infer AT], readonly [infer TH extends string, ...infer TT extends string[]]] ? + Trim extends "|" ? ParseRows : + Trim extends "\n" | "" ? ParseRows : + never : + [A, S] extends [[], readonly []] ? Rows : + never; + +type JestEachArgument = { +>JestEachArgument : JestEachArgument + + [P1 in keyof Rows]: { + [P2 in keyof Headers as P2 extends `${number}` ? Trim : never]: + P2 extends keyof Rows[P1] ? Rows[P1][P2] : undefined; + }; +}[number]; + +type JestEachFunction = (name: string, cb: (arg: Arg) => void, timeout?: number) => void; +>JestEachFunction : JestEachFunction +>name : string +>cb : (arg: Arg) => void +>arg : Arg +>timeout : number | undefined + +type JestEach = +>JestEach : JestEach + + T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ? + JestEachFunction, "|">, ParseRows>> : + null; +>null : null + +declare function each(strs: T, ...args: A): JestEach; +>each : (strs: T, ...args: A) => JestEach +>strs : T +>args : A + +each` +>each` foo | bar ${"a"} | ${1} ${"c"} | ${undefined}`("test", ({ foo, bar }) => { foo; bar;}) : void +>each` foo | bar ${"a"} | ${1} ${"c"} | ${undefined}` : JestEachFunction<{ foo: string; bar: number; } | { foo: string; bar: undefined; }> +>each : (strs: T, ...args: A) => JestEach +>` foo | bar ${"a"} | ${1} ${"c"} | ${undefined}` : string + + foo | bar + ${"a"} | ${1} +>"a" : "a" +>1 : 1 + + ${"c"} | ${undefined} +>"c" : "c" +>undefined : undefined + +`("test", ({ foo, bar }) => { +>"test" : "test" +>({ foo, bar }) => { foo; bar;} : ({ foo, bar }: { foo: string; bar: number; } | { foo: string; bar: undefined; }) => void +>foo : string +>bar : number | undefined + + foo; +>foo : string + + bar; +>bar : number | undefined + +}); + diff --git a/tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts b/tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts index 402887f4cf37e..fa2ad1cc40191 100644 --- a/tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts +++ b/tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts @@ -1,5 +1,6 @@ // @target: esnext // @noEmit: true +// @strict: true // overload resolution declare function f1(array: TemplateStringsArrayOf, ...args: any): "A"; @@ -43,3 +44,49 @@ const raw_r1 = raw`a${1}c`; // "a1c" // "a\\nb\nc" const raw_r2 = raw`a\n${"b"} c`; + +// Jest's `it.each`: +type Whitespace = " " | "\t" | "\v" + +type Trim = + S extends `${Chars}${infer R}` ? Trim : + S extends `${infer R}${Chars}` ? Trim : + S; + +type Split = + S extends D ? [] : + S extends `${infer H}${D}${infer T}` ? [H, ...Split] : + [S]; + +type ParseRows = + [A, S] extends [[infer AH, ...infer AT], readonly [infer TH extends string, ...infer TT extends string[]]] ? + Trim extends "|" ? ParseRows : + Trim extends "\n" | "" ? ParseRows : + never : + [A, S] extends [[], readonly []] ? Rows : + never; + +type JestEachArgument = { + [P1 in keyof Rows]: { + [P2 in keyof Headers as P2 extends `${number}` ? Trim : never]: + P2 extends keyof Rows[P1] ? Rows[P1][P2] : undefined; + }; +}[number]; + +type JestEachFunction = (name: string, cb: (arg: Arg) => void, timeout?: number) => void; + +type JestEach = + T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ? + JestEachFunction, "|">, ParseRows>> : + null; + +declare function each(strs: T, ...args: A): JestEach; + +each` + foo | bar + ${"a"} | ${1} + ${"c"} | ${undefined} +`("test", ({ foo, bar }) => { + foo; + bar; +}); diff --git a/tests/cases/conformance/types/conditional/inferTypes1.ts b/tests/cases/conformance/types/conditional/inferTypes1.ts index b7dc9dcb4180d..61a9dc3c1d9cf 100644 --- a/tests/cases/conformance/types/conditional/inferTypes1.ts +++ b/tests/cases/conformance/types/conditional/inferTypes1.ts @@ -190,4 +190,5 @@ type Foo2 = ReturnType<(...args: A) => string>; // Infer from an intersected tuple type Head = T extends [infer THead, ...infer _] ? THead : never; -type T100 = Head<["a", "c"] & { foo: "bar" }>; +type T100 = Head<["a", "c"] & { foo: "bar" }>; // "a" +type T101 = Head<["a", "c"] & readonly ["a", "c"]>; // "a" | "c" From 95b896b5fefae5ee5b7050f80b857ce742d427be Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 17 Jun 2022 11:20:36 -0700 Subject: [PATCH 3/3] Only check overlaps if we found an array/tuple in the intersection --- src/compiler/checker.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 973d4271e2511..09450cac8e841 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21201,16 +21201,21 @@ namespace ts { } arrayOrTupleConstituent = constituent; } - else { - const properties = getPropertiesOfType(constituent); - for (const property of properties) { - if (isNumericLiteralName(property.escapedName) || property.escapedName === "length" as __String) { - return undefined; + } + + if (arrayOrTupleConstituent) { + for (const constituent of (type as IntersectionType).types) { + if (constituent !== arrayOrTupleConstituent) { + const properties = getPropertiesOfType(constituent); + for (const property of properties) { + if (isNumericLiteralName(property.escapedName) || property.escapedName === "length" as __String) { + return undefined; + } } - } - if (some(getIndexInfosOfType(constituent))) { - return undefined; + if (some(getIndexInfosOfType(constituent))) { + return undefined; + } } } }