More specific TemplateStringsArray type for tagged templates

This commit is contained in:
Ron Buckton
2022-06-15 18:51:19 -07:00
parent 3fc5f968ca
commit 70fdb520b2
35 changed files with 567 additions and 104 deletions
+92 -18
View File
@@ -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<TypeNode> | 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);
}
}
+1 -21
View File
@@ -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
// <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for both TV and TRV.
text = text.replace(/\r\n?/g, "\n");
const text = getRawTextOfTemplateLiteralLike(node, currentSourceFile);
return setTextRange(factory.createStringLiteral(text), node);
}
}
+24
View File
@@ -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
// <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> 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;
+1
View File
@@ -1119,6 +1119,7 @@ namespace FourSlashInterface {
varEntry("Number"),
interfaceEntry("NumberConstructor"),
interfaceEntry("TemplateStringsArray"),
typeEntry("TemplateStringsArrayOf"),
interfaceEntry("ImportMeta"),
interfaceEntry("ImportCallOptions"),
interfaceEntry("ImportAssertions"),
+2
View File
@@ -594,6 +594,8 @@ interface TemplateStringsArray extends ReadonlyArray<string> {
readonly raw: readonly string[];
}
type TemplateStringsArrayOf<Cooked extends readonly string[], Raw extends readonly string[] = Cooked> = Cooked & { readonly raw: Raw };
/**
* The type of `import.meta`.
*
@@ -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]]'.
@@ -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>[]): never[]', gave the following error.
@@ -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) ====
@@ -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.
@@ -31,8 +31,8 @@ function id<T>(x: T) {
}
export const result = id`hello world`;
>result : TemplateStringsArray
>id`hello world` : TemplateStringsArray
>result : TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
>id`hello world` : TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
>id : <T>(x: T) => T
>`hello world` : "hello world"
@@ -69,8 +69,8 @@ function id<T>(x: T) {
}
const result = id`hello world`;
>result : TemplateStringsArray
>id`hello world` : TemplateStringsArray
>result : TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
>id`hello world` : TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
>id : <T>(x: T) => T
>`hello world` : "hello world"
@@ -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<A extends any[]> = ReturnType<(...args: A) => string>;
// Infer from an intersected tuple
type Head<T extends string[]> = T extends [infer THead, ...infer _] ? THead : never;
type T100 = Head<["a", "c"] & { foo: "bar" }>;
+4
View File
@@ -185,6 +185,10 @@ function invoker <K extends string | number | symbol, A extends any[]> (key: K,
const result = invoker('test', true)({ test: (a: boolean) => 123 })
type Foo2<A extends any[]> = ReturnType<(...args: A) => string>;
// Infer from an intersected tuple
type Head<T extends string[]> = T extends [infer THead, ...infer _] ? THead : never;
type T100 = Head<["a", "c"] & { foo: "bar" }>;
//// [inferTypes1.js]
@@ -775,3 +775,17 @@ type Foo2<A extends any[]> = 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 string[]> = 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))
@@ -493,3 +493,11 @@ type Foo2<A extends any[]> = ReturnType<(...args: A) => string>;
>Foo2 : string
>args : A
// Infer from an intersected tuple
type Head<T extends string[]> = T extends [infer THead, ...infer _] ? THead : never;
>Head : Head<T>
type T100 = Head<["a", "c"] & { foo: "bar" }>;
>T100 : "a"
>foo : "bar"
@@ -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>[]): number[]; (...items: (number | ConcatArray<number>)[]): 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: { <S extends number>(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: <U>(callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { <S extends number>(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; <U>(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; <U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; find: { <S extends number>(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<number>; values: () => IterableIterator<number>; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]; flat: <A, D extends number = 1>(this: A, depth?: D) => FlatArray<A, D>[]; [iterator]: () => IterableIterator<number>; [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.
@@ -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 {
@@ -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.
}
@@ -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.
}
@@ -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.
}
@@ -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.
}
@@ -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) {
@@ -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.
}
@@ -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<string>' is not assignable to parameter of type '(error: any) => Promise<number>'.
!!! error TS2769: Property 'catch' is missing in type 'IPromise<string>' but required in type 'Promise<number>'.
!!! 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
@@ -351,7 +351,7 @@ tests/cases/compiler/promisePermutations2.ts(159,21): error TS2345: Argument of
~~~~~~~~~
!!! error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => Promise<number>'.
!!! error TS2345: Property 'catch' is missing in type 'IPromise<string>' but required in type 'Promise<number>'.
!!! 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<number>;
@@ -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<string>' is not assignable to parameter of type '(error: any) => Promise<number>'.
!!! error TS2769: Property 'catch' is missing in type 'IPromise<string>' but required in type 'Promise<number>'.
!!! 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 '{ <T>(x: T): IPromise<T>; <T>(x: T, y: T): Promise<T>; }' is not assignable to parameter of type '(value: (x: any) => any) => Promise<unknown>'.
!!! error TS2345: Property 'catch' is missing in type 'IPromise<any>' but required in type 'Promise<unknown>'.
!!! 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
@@ -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 '<T>(n: number, s: string) => number' but required in type 'ArrayConstructor'.
!!! related TS2728 /.ts/lib.es5.d.ts:1466:5: 'isArray' is declared here.
!!! related TS2728 /.ts/lib.es5.d.ts:1468:5: 'isArray' is declared here.
@@ -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.
}
@@ -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.
}
@@ -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) {
@@ -0,0 +1,160 @@
=== tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts ===
// overload resolution
declare function f1(array: TemplateStringsArrayOf<readonly ["a", ...string[]]>, ...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<readonly ["b", ...string[]]>, ...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<T extends TemplateStringsArray, A extends string[]>(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<readonly ["a", "c"], readonly ["a", "c"]>, ["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<T extends readonly string[], A extends any[], R extends string = ''> =
>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<TT, AT, `${R}${TH}${AH}`> :
>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<TT, [], `${R}${TH}`> :
>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<T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A): Interpolate<T, A>;
>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<T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A): Interpolate<T["raw"], A>;
>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`;
@@ -0,0 +1,143 @@
=== tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts ===
// overload resolution
declare function f1(array: TemplateStringsArrayOf<readonly ["a", ...string[]]>, ...args: any): "A";
>f1 : { (array: TemplateStringsArrayOf<readonly ["a", ...string[]]>, ...args: any): "A"; (array: TemplateStringsArrayOf<readonly ["b", ...string[]], readonly ["b", ...string[]]>, ...args: any): "B"; (array: TemplateStringsArray, ...args: any): "C"; }
>array : TemplateStringsArrayOf<readonly ["a", ...string[]], readonly ["a", ...string[]]>
>args : any
declare function f1(array: TemplateStringsArrayOf<readonly ["b", ...string[]]>, ...args: any): "B";
>f1 : { (array: TemplateStringsArrayOf<readonly ["a", ...string[]], readonly ["a", ...string[]]>, ...args: any): "A"; (array: TemplateStringsArrayOf<readonly ["b", ...string[]]>, ...args: any): "B"; (array: TemplateStringsArray, ...args: any): "C"; }
>array : TemplateStringsArrayOf<readonly ["b", ...string[]], readonly ["b", ...string[]]>
>args : any
declare function f1(array: TemplateStringsArray, ...args: any): "C";
>f1 : { (array: TemplateStringsArrayOf<readonly ["a", ...string[]], readonly ["a", ...string[]]>, ...args: any): "A"; (array: TemplateStringsArrayOf<readonly ["b", ...string[]], readonly ["b", ...string[]]>, ...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<readonly ["a", ...string[]], readonly ["a", ...string[]]>, ...args: any): "A"; (array: TemplateStringsArrayOf<readonly ["b", ...string[]], readonly ["b", ...string[]]>, ...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<readonly ["a", ...string[]], readonly ["a", ...string[]]>, ...args: any): "A"; (array: TemplateStringsArrayOf<readonly ["b", ...string[]], readonly ["b", ...string[]]>, ...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<readonly ["a", ...string[]], readonly ["a", ...string[]]>, ...args: any): "A"; (array: TemplateStringsArrayOf<readonly ["b", ...string[]], readonly ["b", ...string[]]>, ...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<readonly ["a", ...string[]], readonly ["a", ...string[]]>, ...args: any): "A"; (array: TemplateStringsArrayOf<readonly ["b", ...string[]], readonly ["b", ...string[]]>, ...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<readonly ["a", ...string[]], readonly ["a", ...string[]]>, ...args: any): "A"; (array: TemplateStringsArrayOf<readonly ["b", ...string[]], readonly ["b", ...string[]]>, ...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<readonly ["a", ...string[]], readonly ["a", ...string[]]>, ...args: any): "A"; (array: TemplateStringsArrayOf<readonly ["b", ...string[]], readonly ["b", ...string[]]>, ...args: any): "B"; (array: TemplateStringsArray, ...args: any): "C"; }
>`c${"b"}` : string
>"b" : "b"
// constrained type parameter
declare function f0<T extends TemplateStringsArray, A extends string[]>(array: T, ...args: A): [T, A];
>f0 : <T extends TemplateStringsArray, A extends string[]>(array: T, ...args: A) => [T, A]
>array : T
>args : A
const f0_r0 = f0`a${"b"}c`; // [TemplateStringsArrayOf<readonly ["a", "c"], readonly ["a", "c"]>, ["b"]]
>f0_r0 : [TemplateStringsArrayOf<readonly ["a", "c"], readonly ["a", "c"]>, ["b"]]
>f0`a${"b"}c` : [TemplateStringsArrayOf<readonly ["a", "c"], readonly ["a", "c"]>, ["b"]]
>f0 : <T extends TemplateStringsArray, A extends string[]>(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<T extends readonly string[], A extends any[], R extends string = ''> =
>Interpolate : Interpolate<T, A, R>
T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ?
A extends [infer AH extends TemplatePrimitive, ...infer AT extends TemplatePrimitive[]] ?
Interpolate<TT, AT, `${R}${TH}${AH}`> :
Interpolate<TT, [], `${R}${TH}`> :
R;
// string interpolation
declare function interp<T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A): Interpolate<T, A>;
>interp : <T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A) => Interpolate<T, A>
>array : T
>args : A
const interp_r0 = interp`a${"b"}c`; // "abc"
>interp_r0 : "abc"
>interp`a${"b"}c` : "abc"
>interp : <T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A) => Interpolate<T, A, "">
>`a${"b"}c` : string
>"b" : "b"
const interp_r1 = interp`a${1}c`; // "a1c"
>interp_r1 : "a1c"
>interp`a${1}c` : "a1c"
>interp : <T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A) => Interpolate<T, A, "">
>`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 : <T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A) => Interpolate<T, A, "">
>`a\n${"b"}c` : string
>"b" : "b"
c`;
// raw string interpolation (i.e., 'String.raw')
declare function raw<T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A): Interpolate<T["raw"], A>;
>raw : <T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A) => Interpolate<T["raw"], A>
>array : T
>args : A
const raw_r0 = raw`a${"b"}c`; // "abc"
>raw_r0 : "abc"
>raw`a${"b"}c` : "abc"
>raw : <T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A) => Interpolate<T["raw"], A, "">
>`a${"b"}c` : string
>"b" : "b"
const raw_r1 = raw`a${1}c`; // "a1c"
>raw_r1 : "a1c"
>raw`a${1}c` : "a1c"
>raw : <T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A) => Interpolate<T["raw"], A, "">
>`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 : <T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A) => Interpolate<T["raw"], A, "">
>`a\n${"b"}c` : string
>"b" : "b"
c`;
@@ -8,8 +8,8 @@ function id<T>(x: T) {
}
export const result = id `hello world`;
>result : TemplateStringsArray
>id `hello world` : TemplateStringsArray
>result : TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
>id `hello world` : TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
>id : <T>(x: T) => T
>`hello world` : "hello world"
@@ -11,20 +11,20 @@ namespace n {
}
function templateObjectFactory() {
>templateObjectFactory : () => TemplateStringsArray
>templateObjectFactory : () => TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
return id`hello world`;
>id`hello world` : TemplateStringsArray
>id`hello world` : TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
>id : <T>(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<readonly ["hello world"], readonly ["hello world"]>
>templateObjectFactory : () => TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
>templateObjectFactory() : TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
>templateObjectFactory : () => TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
}
=== tests/cases/compiler/module.ts ===
export { }
@@ -37,18 +37,18 @@ function id<T>(x: T): T {
}
function templateObjectFactory() {
>templateObjectFactory : () => TemplateStringsArray
>templateObjectFactory : () => TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
return id`hello world`;
>id`hello world` : TemplateStringsArray
>id`hello world` : TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
>id : <T>(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<readonly ["hello world"], readonly ["hello world"]>
>templateObjectFactory : () => TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
>templateObjectFactory() : TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
>templateObjectFactory : () => TemplateStringsArrayOf<readonly ["hello world"], readonly ["hello world"]>
@@ -0,0 +1,45 @@
// @target: esnext
// @noEmit: true
// overload resolution
declare function f1(array: TemplateStringsArrayOf<readonly ["a", ...string[]]>, ...args: any): "A";
declare function f1(array: TemplateStringsArrayOf<readonly ["b", ...string[]]>, ...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<T extends TemplateStringsArray, A extends string[]>(array: T, ...args: A): [T, A];
const f0_r0 = f0`a${"b"}c`; // [TemplateStringsArrayOf<readonly ["a", "c"], readonly ["a", "c"]>, ["b"]]
// interpolation example
type TemplatePrimitive = string | number | bigint | boolean | null | undefined;
type Interpolate<T extends readonly string[], A extends any[], R extends string = ''> =
T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ?
A extends [infer AH extends TemplatePrimitive, ...infer AT extends TemplatePrimitive[]] ?
Interpolate<TT, AT, `${R}${TH}${AH}`> :
Interpolate<TT, [], `${R}${TH}`> :
R;
// string interpolation
declare function interp<T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A): Interpolate<T, A>;
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<T extends TemplateStringsArray, A extends TemplatePrimitive[]>(array: T, ...args: A): Interpolate<T["raw"], A>;
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`;
@@ -187,3 +187,7 @@ function invoker <K extends string | number | symbol, A extends any[]> (key: K,
const result = invoker('test', true)({ test: (a: boolean) => 123 })
type Foo2<A extends any[]> = ReturnType<(...args: A) => string>;
// Infer from an intersected tuple
type Head<T extends string[]> = T extends [infer THead, ...infer _] ? THead : never;
type T100 = Head<["a", "c"] & { foo: "bar" }>;