diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f112e25b18b21..246f3d1505020 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -698,6 +698,7 @@ namespace ts { const intersectionTypes = new Map(); const literalTypes = new Map(); const indexedAccessTypes = new Map(); + const templateLiteralTypes = new Map(); const substitutionTypes = new Map(); const evolvingArrayTypes: EvolvingArrayType[] = []; const undefinedProperties: SymbolTable = new Map(); @@ -748,6 +749,7 @@ namespace ts { const stringNumberSymbolType = getUnionType([stringType, numberType, esSymbolType]); const keyofConstraintType = keyofStringsOnly ? stringType : stringNumberSymbolType; const numberOrBigIntType = getUnionType([numberType, bigintType]); + const templateConstraintType = getUnionType([stringType, numberType, booleanType, bigintType]); const restrictiveMapper: TypeMapper = makeFunctionTypeMapper(t => t.flags & TypeFlags.TypeParameter ? getRestrictiveTypeParameter(t) : t); const permissiveMapper: TypeMapper = makeFunctionTypeMapper(t => t.flags & TypeFlags.TypeParameter ? wildcardType : t); @@ -4489,6 +4491,19 @@ namespace ts { const indexTypeNode = typeToTypeNodeHelper(indexedType, context); return factory.createTypeOperatorNode(SyntaxKind.KeyOfKeyword, indexTypeNode); } + if (type.flags & TypeFlags.TemplateLiteral) { + const texts = (type).texts; + const casings = (type).casings; + const types = (type).types; + const templateHead = factory.createTemplateHead(texts[0]); + const templateSpans = factory.createNodeArray( + map(types, (t, i) => factory.createTemplateLiteralTypeSpan( + casings[i], + typeToTypeNodeHelper(t, context), + (i < types.length - 1 ? factory.createTemplateMiddle : factory.createTemplateTail)(texts[i + 1])))); + context.approximateLength += 2; + return factory.createTemplateLiteralType(templateHead, templateSpans); + } if (type.flags & TypeFlags.IndexedAccess) { const objectTypeNode = typeToTypeNodeHelper((type).objectType, context); const indexTypeNode = typeToTypeNodeHelper((type).indexType, context); @@ -4541,8 +4556,9 @@ namespace ts { appropriateConstraintTypeNode = typeToTypeNodeHelper(getConstraintTypeFromMappedType(type), context); } const typeParameterNode = typeParameterToDeclarationWithConstraint(getTypeParameterFromMappedType(type), context, appropriateConstraintTypeNode); + const nameTypeNode = type.declaration.nameType ? typeToTypeNodeHelper(getNameTypeFromMappedType(type)!, context) : undefined; const templateTypeNode = typeToTypeNodeHelper(getTemplateTypeFromMappedType(type), context); - const mappedTypeNode = factory.createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode); + const mappedTypeNode = factory.createMappedTypeNode(readonlyToken, typeParameterNode, nameTypeNode, questionToken, templateTypeNode); context.approximateLength += 10; return setEmitFlags(mappedTypeNode, EmitFlags.SingleLine); } @@ -10350,9 +10366,6 @@ namespace ts { // bound includes those keys that are known to always be present, for example because // because of constraints on type parameters (e.g. 'keyof T' for a constrained T). function getLowerBoundOfKeyType(type: Type): Type { - if (type.flags & (TypeFlags.Any | TypeFlags.Primitive)) { - return type; - } if (type.flags & TypeFlags.Index) { const t = getApparentType((type).type); return isGenericTupleType(t) ? getKnownKeysOfTupleType(t) : getIndexType(t); @@ -10373,7 +10386,7 @@ namespace ts { if (type.flags & TypeFlags.Intersection) { return getIntersectionType(sameMap((type).types, getLowerBoundOfKeyType)); } - return neverType; + return type; } /** Resolve the members of a mapped type { [P in K]: T } */ @@ -10387,6 +10400,7 @@ namespace ts { // and T as the template type. const typeParameter = getTypeParameterFromMappedType(type); const constraintType = getConstraintTypeFromMappedType(type); + const nameType = getNameTypeFromMappedType(type.target || type); const templateType = getTemplateTypeFromMappedType(type.target || type); const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T' const templateModifiers = getMappedTypeModifiers(type); @@ -10408,22 +10422,23 @@ namespace ts { } setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); - function addMemberForKeyType(t: Type) { - // Create a mapper from T to the current iteration type constituent. Then, if the - // mapped type is itself an instantiated type, combine the iteration mapper with the - // instantiation mapper. - const templateMapper = appendTypeMapping(type.mapper, typeParameter, t); + function addMemberForKeyType(keyType: Type) { + const propNameType = nameType ? instantiateType(nameType, appendTypeMapping(type.mapper, typeParameter, keyType)) : keyType; + forEachType(propNameType, t => addMemberForKeyTypeWorker(keyType, t)); + } + + function addMemberForKeyTypeWorker(keyType: Type, propNameType: Type) { // If the current iteration type constituent is a string literal type, create a property. // Otherwise, for type string create a string index signature. - if (isTypeUsableAsPropertyName(t)) { - const propName = getPropertyNameFromType(t); + if (isTypeUsableAsPropertyName(propNameType)) { + const propName = getPropertyNameFromType(propNameType); // String enum members from separate enums with identical values // are distinct types with the same property name. Make the resulting // property symbol's name type be the union of those enum member types. const existingProp = members.get(propName) as MappedSymbol | undefined; if (existingProp) { - existingProp.nameType = getUnionType([existingProp.nameType!, t]); - existingProp.mapper = appendTypeMapping(type.mapper, typeParameter, existingProp.nameType); + existingProp.nameType = getUnionType([existingProp.nameType!, propNameType]); + existingProp.keyType = getUnionType([existingProp.keyType, keyType]); } else { const modifiersProp = getPropertyOfType(modifiersType, propName); @@ -10435,19 +10450,20 @@ namespace ts { const prop = createSymbol(SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), propName, CheckFlags.Mapped | (isReadonly ? CheckFlags.Readonly : 0) | (stripOptional ? CheckFlags.StripOptional : 0)); prop.mappedType = type; + prop.nameType = propNameType; + prop.keyType = keyType; if (modifiersProp) { prop.syntheticOrigin = modifiersProp; prop.declarations = modifiersProp.declarations; } - prop.nameType = t; - prop.mapper = templateMapper; members.set(propName, prop); } } - else if (t.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.Enum)) { - const propType = instantiateType(templateType, templateMapper); - if (t.flags & (TypeFlags.Any | TypeFlags.String)) { - stringIndexInfo = createIndexInfo(propType, !!(templateModifiers & MappedTypeModifiers.IncludeReadonly)); + else if (propNameType.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.Enum)) { + const propType = instantiateType(templateType, appendTypeMapping(type.mapper, typeParameter, keyType)); + if (propNameType.flags & (TypeFlags.Any | TypeFlags.String)) { + stringIndexInfo = createIndexInfo(stringIndexInfo ? getUnionType([stringIndexInfo.type, propType]) : propType, + !!(templateModifiers & MappedTypeModifiers.IncludeReadonly)); } else { numberIndexInfo = createIndexInfo(numberIndexInfo ? getUnionType([numberIndexInfo.type, propType]) : propType, @@ -10459,12 +10475,14 @@ namespace ts { function getTypeOfMappedSymbol(symbol: MappedSymbol) { if (!symbol.type) { + const mappedType = symbol.mappedType; if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { - symbol.mappedType.containsError = true; + mappedType.containsError = true; return errorType; } - const templateType = getTemplateTypeFromMappedType(symbol.mappedType.target || symbol.mappedType); - const propType = instantiateType(templateType, symbol.mapper); + const templateType = getTemplateTypeFromMappedType(mappedType.target || mappedType); + const mapper = appendTypeMapping(mappedType.mapper, getTypeParameterFromMappedType(mappedType), symbol.keyType); + const propType = instantiateType(templateType, mapper); // When creating an optional property in strictNullChecks mode, if 'undefined' isn't assignable to the // type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks // mode, if the underlying property is optional we remove 'undefined' from the type. @@ -10472,11 +10490,10 @@ namespace ts { symbol.checkFlags & CheckFlags.StripOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) : propType; if (!popTypeResolution()) { - error(currentNode, Diagnostics.Type_of_property_0_circularly_references_itself_in_mapped_type_1, symbolToString(symbol), typeToString(symbol.mappedType)); + error(currentNode, Diagnostics.Type_of_property_0_circularly_references_itself_in_mapped_type_1, symbolToString(symbol), typeToString(mappedType)); type = errorType; } symbol.type = type; - symbol.mapper = undefined!; } return symbol.type; } @@ -10491,6 +10508,12 @@ namespace ts { (type.constraintType = getConstraintOfTypeParameter(getTypeParameterFromMappedType(type)) || errorType); } + function getNameTypeFromMappedType(type: MappedType) { + return type.declaration.nameType ? + type.nameType || (type.nameType = instantiateType(getTypeFromTypeNode(type.declaration.nameType), type.mapper)) : + undefined; + } + function getTemplateTypeFromMappedType(type: MappedType) { return type.templateType || (type.templateType = type.declaration.type ? @@ -10784,7 +10807,7 @@ namespace ts { } function getBaseConstraintOfType(type: Type): Type | undefined { - if (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.UnionOrIntersection)) { + if (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral)) { const constraint = getResolvedBaseConstraint(type); return constraint !== noConstraintType && constraint !== circularConstraintType ? constraint : undefined; } @@ -10878,6 +10901,11 @@ namespace ts { if (t.flags & TypeFlags.Index) { return keyofConstraintType; } + if (t.flags & TypeFlags.TemplateLiteral) { + const types = (t).types; + const constraints = mapDefined(types, getBaseConstraint); + return constraints.length === types.length ? getTemplateLiteralType((t).texts, (t).casings, constraints) : stringType; + } if (t.flags & TypeFlags.IndexedAccess) { const baseObjectType = getBaseConstraint((t).objectType); const baseIndexType = getBaseConstraint((t).indexType); @@ -10955,7 +10983,7 @@ namespace ts { function getResolvedApparentTypeOfMappedType(type: MappedType) { const typeVariable = getHomomorphicTypeVariable(type); - if (typeVariable) { + if (typeVariable && !type.declaration.nameType) { const constraint = getConstraintOfTypeParameter(typeVariable); if (constraint && (isArrayType(constraint) || isTupleType(constraint))) { return instantiateType(type, prependTypeMapping(typeVariable, constraint, type.mapper)); @@ -11895,6 +11923,11 @@ namespace ts { grandParent.kind === SyntaxKind.NamedTupleMember && (grandParent).dotDotDotToken) { inferences = append(inferences, createArrayType(unknownType)); } + // When an 'infer T' declaration is immediately contained in a string template type, we infer a 'string' + // constraint. + else if (grandParent.kind === SyntaxKind.TemplateLiteralTypeSpan) { + inferences = append(inferences, stringType); + } } } } @@ -12720,7 +12753,9 @@ namespace ts { // Transform [A, ...(X | Y | Z)] into [A, ...X] | [A, ...Y] | [A, ...Z] const unionIndex = findIndex(elementTypes, (t, i) => !!(target.elementFlags[i] & ElementFlags.Variadic && t.flags & (TypeFlags.Never | TypeFlags.Union))); if (unionIndex >= 0) { - return mapType(elementTypes[unionIndex], t => createNormalizedTupleType(target, replaceElement(elementTypes, unionIndex, t))); + return checkCrossProductUnion(map(elementTypes, (t, i) => target.elementFlags[i] & ElementFlags.Variadic ? t : unknownType)) ? + mapType(elementTypes[unionIndex], t => createNormalizedTupleType(target, replaceElement(elementTypes, unionIndex, t))) : + errorType; } // If there are no variadic elements with non-generic types, just create a type reference with the same target type. const spreadIndex = findIndex(elementTypes, (t, i) => !!(target.elementFlags[i] & ElementFlags.Variadic) && !(t.flags & TypeFlags.InstantiableNonPrimitive) && !isGenericMappedType(t)); @@ -13257,9 +13292,7 @@ namespace ts { // We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of // the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain. // If the estimated size of the resulting union type exceeds 100000 constituents, report an error. - const size = reduceLeft(typeSet, (n, t) => n * (t.flags & TypeFlags.Union ? (t).types.length : 1), 1); - if (size >= 100000) { - error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent); + if (!checkCrossProductUnion(typeSet)) { return errorType; } const unionIndex = findIndex(typeSet, t => (t.flags & TypeFlags.Union) !== 0); @@ -13276,6 +13309,15 @@ namespace ts { return result; } + function checkCrossProductUnion(types: readonly Type[]) { + const size = reduceLeft(types, (n, t) => n * (t.flags & TypeFlags.Union ? (t).types.length : t.flags & TypeFlags.Never ? 0 : 1), 1); + if (size >= 100000) { + error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent); + return false; + } + return true; + } + function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { @@ -13299,6 +13341,13 @@ namespace ts { type.resolvedIndexType || (type.resolvedIndexType = createIndexType(type, /*stringsOnly*/ false)); } + function getIndexTypeForMappedType(type: MappedType, noIndexSignatures: boolean | undefined) { + const constraint = filterType(getConstraintTypeFromMappedType(type), t => !(noIndexSignatures && t.flags & (TypeFlags.Any | TypeFlags.String))); + return type.declaration.nameType ? + instantiateType(getTypeFromTypeNode(type.declaration.nameType), appendTypeMapping(type.mapper, getTypeParameterFromMappedType(type), constraint)) : + constraint; + } + function getLiteralTypeFromPropertyName(name: PropertyName) { if (isPrivateIdentifier(name)) { return neverType; @@ -13347,7 +13396,7 @@ namespace ts { return type.flags & TypeFlags.Union ? getIntersectionType(map((type).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) : type.flags & TypeFlags.Intersection ? getUnionType(map((type).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) : type.flags & TypeFlags.InstantiableNonPrimitive || isGenericTupleType(type) ? getIndexTypeForGenericType(type, stringsOnly) : - getObjectFlags(type) & ObjectFlags.Mapped ? filterType(getConstraintTypeFromMappedType(type), t => !(noIndexSignatures && t.flags & (TypeFlags.Any | TypeFlags.String))) : + getObjectFlags(type) & ObjectFlags.Mapped ? getIndexTypeForMappedType(type, noIndexSignatures) : type === wildcardType ? wildcardType : type.flags & TypeFlags.Unknown ? neverType : type.flags & (TypeFlags.Any | TypeFlags.Never) ? keyofConstraintType : @@ -13392,6 +13441,83 @@ namespace ts { return links.resolvedType; } + function getTypeFromTemplateTypeNode(node: TemplateLiteralTypeNode) { + const links = getNodeLinks(node); + if (!links.resolvedType) { + links.resolvedType = getTemplateLiteralType( + [node.head.text, ...map(node.templateSpans, span => span.literal.text)], + map(node.templateSpans, span => span.casing), + map(node.templateSpans, span => getTypeFromTypeNode(span.type))); + } + return links.resolvedType; + } + + function getTemplateLiteralType(texts: readonly string[], casings: readonly TemplateCasing[], types: readonly Type[]): Type { + const unionIndex = findIndex(types, t => !!(t.flags & (TypeFlags.Never | TypeFlags.Union))); + if (unionIndex >= 0) { + return checkCrossProductUnion(types) ? + mapType(types[unionIndex], t => getTemplateLiteralType(texts, casings, replaceElement(types, unionIndex, t))) : + errorType; + } + const newTypes = []; + const newCasings = []; + const newTexts = []; + let text = texts[0]; + for (let i = 0; i < types.length; i++) { + const t = types[i]; + if (t.flags & TypeFlags.Literal) { + const s = applyTemplateCasing(getTemplateStringForType(t) || "", casings[i]); + text += s; + text += texts[i + 1]; + } + else if (isGenericIndexType(t)) { + newTypes.push(t); + newCasings.push(casings[i]); + newTexts.push(text); + text = texts[i + 1]; + } + else { + return stringType; + } + } + if (newTypes.length === 0) { + return getLiteralType(text); + } + newTexts.push(text); + const id = `${getTypeListId(newTypes)}|${newCasings.join(",")}|${map(newTexts, t => t.length).join(",")}|${newTexts.join("")}`; + let type = templateLiteralTypes.get(id); + if (!type) { + templateLiteralTypes.set(id, type = createTemplateLiteralType(newTexts, newCasings, newTypes)); + } + return type; + } + + function getTemplateStringForType(type: Type) { + return type.flags & TypeFlags.StringLiteral ? (type).value : + type.flags & TypeFlags.NumberLiteral ? "" + (type).value : + type.flags & TypeFlags.BigIntLiteral ? pseudoBigIntToString((type).value) : + type.flags & TypeFlags.BooleanLiteral ? (type).intrinsicName : + undefined; + } + + function applyTemplateCasing(str: string, casing: TemplateCasing) { + switch (casing) { + case TemplateCasing.Uppercase: return str.toUpperCase(); + case TemplateCasing.Lowercase: return str.toLowerCase(); + case TemplateCasing.Capitalize: return str.charAt(0).toUpperCase() + str.slice(1); + case TemplateCasing.Uncapitalize: return str.charAt(0).toLowerCase() + str.slice(1); + } + return str; + } + + function createTemplateLiteralType(texts: readonly string[], casings: readonly TemplateCasing[], types: readonly Type[]) { + const type = createType(TypeFlags.TemplateLiteral); + type.texts = texts; + type.casings = casings; + type.types = types; + return type; + } + function createIndexedAccessType(objectType: Type, indexType: Type, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) { const type = createType(TypeFlags.IndexedAccess); type.objectType = objectType; @@ -13624,7 +13750,7 @@ namespace ts { } return !!((type).objectFlags & ObjectFlags.IsGenericIndexType); } - return !!(type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index)); + return !!(type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index | TypeFlags.TemplateLiteral)); } function isThisTypeParameter(type: Type): boolean { @@ -14122,7 +14248,7 @@ namespace ts { } function isEmptyObjectTypeOrSpreadsIntoEmptyObject(type: Type) { - return isEmptyObjectType(type) || !!(type.flags & (TypeFlags.Null | TypeFlags.Undefined | TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)); + return isEmptyObjectType(type) || !!(type.flags & (TypeFlags.Null | TypeFlags.Undefined | TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index | TypeFlags.TemplateLiteral)); } function isSinglePropertyAnonymousObjectType(type: Type) { @@ -14208,7 +14334,7 @@ namespace ts { } return mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly)); } - if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)) { + if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index | TypeFlags.TemplateLiteral)) { return left; } @@ -14540,6 +14666,8 @@ namespace ts { return getTypeFromConditionalTypeNode(node); case SyntaxKind.InferType: return getTypeFromInferTypeNode(node); + case SyntaxKind.TemplateLiteralType: + return getTypeFromTemplateTypeNode(node); case SyntaxKind.ImportType: return getTypeFromImportTypeNode(node); // This function assumes that an identifier, qualified name, or property access expression is a type expression @@ -14837,13 +14965,18 @@ namespace ts { if (typeVariable !== mappedTypeVariable) { return mapType(getReducedType(mappedTypeVariable), t => { if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && t !== errorType) { - if (isGenericTupleType(t)) { - return instantiateMappedGenericTupleType(t, type, typeVariable, mapper); + if (!type.declaration.nameType) { + if (isArrayType(t)) { + return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); + } + if (isGenericTupleType(t)) { + return instantiateMappedGenericTupleType(t, type, typeVariable, mapper); + } + if (isTupleType(t)) { + return instantiateMappedTupleType(t, type, prependTypeMapping(typeVariable, t, mapper)); + } } - const replacementMapper = prependTypeMapping(typeVariable, t, mapper); - return isArrayType(t) ? instantiateMappedArrayType(t, type, replacementMapper) : - isTupleType(t) ? instantiateMappedTupleType(t, type, replacementMapper) : - instantiateAnonymousType(type, replacementMapper); + return instantiateAnonymousType(type, prependTypeMapping(typeVariable, t, mapper)); } return t; }); @@ -15001,6 +15134,9 @@ namespace ts { if (flags & TypeFlags.Index) { return getIndexType(instantiateType((type).type, mapper)); } + if (flags & TypeFlags.TemplateLiteral) { + return getTemplateLiteralType((type).texts, (type).casings, instantiateTypes((type).types, mapper)); + } if (flags & TypeFlags.IndexedAccess) { return getIndexedAccessType(instantiateType((type).objectType, mapper), instantiateType((type).indexType, mapper), /*accessNode*/ undefined, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)); } @@ -16987,7 +17123,8 @@ namespace ts { if (target.flags & TypeFlags.TypeParameter) { // A source type { [P in Q]: X } is related to a target type T if keyof T is related to Q and X is related to T[Q]. - if (getObjectFlags(source) & ObjectFlags.Mapped && isRelatedTo(getIndexType(target), getConstraintTypeFromMappedType(source))) { + if (getObjectFlags(source) & ObjectFlags.Mapped && !(source).declaration.nameType && isRelatedTo(getIndexType(target), getConstraintTypeFromMappedType(source))) { + if (!(getMappedTypeModifiers(source) & MappedTypeModifiers.IncludeOptional)) { const templateType = getTemplateTypeFromMappedType(source); const indexedAccessType = getIndexedAccessType(target, getTypeParameterFromMappedType(source)); @@ -17044,7 +17181,7 @@ namespace ts { } } } - else if (isGenericMappedType(target)) { + else if (isGenericMappedType(target) && !target.declaration.nameType) { // A source type T is related to a target type { [P in X]: T[P] } const template = getTemplateTypeFromMappedType(target); const modifiers = getMappedTypeModifiers(target); @@ -17126,6 +17263,13 @@ namespace ts { return result; } } + else if (source.flags & TypeFlags.TemplateLiteral) { + const constraint = getBaseConstraintOfType(source); + if (constraint && (result = isRelatedTo(constraint, target, reportErrors))) { + resetErrorInfo(saveErrorInfo); + return result; + } + } else if (source.flags & TypeFlags.Conditional) { if (target.flags & TypeFlags.Conditional) { // Two conditional types 'T1 extends U1 ? X1 : Y1' and 'T2 extends U2 ? X2 : Y2' are related if @@ -17339,7 +17483,9 @@ namespace ts { const sourceConstraint = instantiateType(getConstraintTypeFromMappedType(source), makeFunctionTypeMapper(getCombinedMappedTypeOptionality(source) < 0 ? reportUnmeasurableMarkers : reportUnreliableMarkers)); if (result = isRelatedTo(targetConstraint, sourceConstraint, reportErrors)) { const mapper = createTypeMapper([getTypeParameterFromMappedType(source)], [getTypeParameterFromMappedType(target)]); - return result & isRelatedTo(instantiateType(getTemplateTypeFromMappedType(source), mapper), getTemplateTypeFromMappedType(target), reportErrors); + if (instantiateType(getNameTypeFromMappedType(source), mapper) === instantiateType(getNameTypeFromMappedType(target), mapper)) { + return result & isRelatedTo(instantiateType(getTemplateTypeFromMappedType(source), mapper), getTemplateTypeFromMappedType(target), reportErrors); + } } } return Ternary.False; @@ -19575,6 +19721,9 @@ namespace ts { inferFromTypes(sourceType, target); } } + else if (target.flags & TypeFlags.TemplateLiteral) { + inferToTemplateLiteralType(source, target); + } else { source = getReducedType(source); if (!(priority & InferencePriority.NoConstraints && source.flags & (TypeFlags.Intersection | TypeFlags.Instantiable))) { @@ -19627,8 +19776,8 @@ namespace ts { // We stop inferring and report a circularity if we encounter duplicate recursion identities on both // the source side and the target side. const saveExpandingFlags = expandingFlags; - const sourceIdentity = getRecursionIdentity(source); - const targetIdentity = getRecursionIdentity(target); + const sourceIdentity = getRecursionIdentity(source) || source; + const targetIdentity = getRecursionIdentity(target) || target; if (sourceIdentity && contains(sourceStack, sourceIdentity)) expandingFlags |= ExpandingFlags.Source; if (targetIdentity && contains(targetStack, targetIdentity)) expandingFlags |= ExpandingFlags.Target; if (expandingFlags !== ExpandingFlags.Both) { @@ -19853,6 +20002,39 @@ namespace ts { } } + function inferToTemplateLiteralType(source: Type, target: TemplateLiteralType) { + if (source.flags & (TypeFlags.StringLike | TypeFlags.Index)) { + const matches = source.flags & TypeFlags.StringLiteral ? inferLiteralsFromTemplateLiteralType(source, target) : + source.flags & TypeFlags.TemplateLiteral && arraysEqual((source).texts, target.texts) && arraysEqual((source).casings, target.casings)? (source).types : + undefined; + const types = target.types; + for (let i = 0; i < types.length; i++) { + inferFromTypes(matches ? matches[i] : source.flags & TypeFlags.StringLiteral ? neverType : stringType, types[i]); + } + } + } + + function inferLiteralsFromTemplateLiteralType(source: StringLiteralType, target: TemplateLiteralType): Type[] | undefined { + const value = source.value; + const texts = target.texts; + const lastIndex = texts.length - 1; + const startText = texts[0]; + const endText = texts[lastIndex]; + if (!(value.startsWith(startText) && value.endsWith(endText))) return undefined; + const matches = []; + const str = value.slice(startText.length, value.length - endText.length); + let pos = 0; + for (let i = 1; i < lastIndex; i++) { + const delim = texts[i]; + const delimPos = delim.length > 0 ? str.indexOf(delim, pos) : pos < str.length ? pos + 1 : -1; + if (delimPos < 0) return undefined; + matches.push(getLiteralType(str.slice(pos, delimPos))); + pos = delimPos + delim.length; + } + matches.push(getLiteralType(str.slice(pos))); + return matches; + } + function inferFromObjectTypes(source: Type, target: Type) { if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && ( (source).target === (target).target || isArrayType(source) && isArrayType(target))) { @@ -19865,8 +20047,11 @@ namespace ts { // from S to T and from X to Y. inferFromTypes(getConstraintTypeFromMappedType(source), getConstraintTypeFromMappedType(target)); inferFromTypes(getTemplateTypeFromMappedType(source), getTemplateTypeFromMappedType(target)); + const sourceNameType = getNameTypeFromMappedType(source); + const targetNameType = getNameTypeFromMappedType(target); + if (sourceNameType && targetNameType) inferFromTypes(sourceNameType, targetNameType); } - if (getObjectFlags(target) & ObjectFlags.Mapped) { + if (getObjectFlags(target) & ObjectFlags.Mapped && !(target).declaration.nameType) { const constraintType = getConstraintTypeFromMappedType(target); if (inferToMappedType(source, target, constraintType)) { return; @@ -20015,7 +20200,7 @@ namespace ts { function hasPrimitiveConstraint(type: TypeParameter): boolean { const constraint = getConstraintOfTypeParameter(type); - return !!constraint && maybeTypeOfKind(constraint.flags & TypeFlags.Conditional ? getDefaultConstraintOfConditionalType(constraint as ConditionalType) : constraint, TypeFlags.Primitive | TypeFlags.Index); + return !!constraint && maybeTypeOfKind(constraint.flags & TypeFlags.Conditional ? getDefaultConstraintOfConditionalType(constraint as ConditionalType) : constraint, TypeFlags.Primitive | TypeFlags.Index | TypeFlags.TemplateLiteral); } function isObjectLiteralType(type: Type) { @@ -26059,7 +26244,7 @@ namespace ts { else { const contextualType = getIndexedAccessType(restType, getLiteralType(i - index)); const argType = checkExpressionWithContextualType(arg, contextualType, context, checkMode); - const hasPrimitiveContextualType = maybeTypeOfKind(contextualType, TypeFlags.Primitive | TypeFlags.Index); + const hasPrimitiveContextualType = maybeTypeOfKind(contextualType, TypeFlags.Primitive | TypeFlags.Index | TypeFlags.TemplateLiteral); types.push(hasPrimitiveContextualType ? getRegularTypeOfLiteralType(argType) : getWidenedLiteralType(argType)); flags.push(ElementFlags.Required); } @@ -29098,7 +29283,7 @@ namespace ts { // and the right operand to be of type Any, an object type, or a type parameter type. // The result is always of the Boolean primitive type. if (!(allTypesAssignableToKind(leftType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike) || - isTypeAssignableToKind(leftType, TypeFlags.Index | TypeFlags.TypeParameter))) { + isTypeAssignableToKind(leftType, TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.TypeParameter))) { error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol); } if (!allTypesAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive)) { @@ -30047,7 +30232,7 @@ namespace ts { } // If the contextual type is a literal of a particular primitive type, we consider this a // literal context for all literals of that primitive type. - return !!(contextualType.flags & (TypeFlags.StringLiteral | TypeFlags.Index) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) || + return !!(contextualType.flags & (TypeFlags.StringLiteral | TypeFlags.Index | TypeFlags.TemplateLiteral) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) || contextualType.flags & TypeFlags.NumberLiteral && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) || contextualType.flags & TypeFlags.BigIntLiteral && maybeTypeOfKind(candidateType, TypeFlags.BigIntLiteral) || contextualType.flags & TypeFlags.BooleanLiteral && maybeTypeOfKind(candidateType, TypeFlags.BooleanLiteral) || @@ -31206,10 +31391,12 @@ namespace ts { } } forEach(node.elements, checkSourceElement); + getTypeFromTypeNode(node); } function checkUnionOrIntersectionType(node: UnionOrIntersectionTypeNode) { forEach(node.types, checkSourceElement); + getTypeFromTypeNode(node); } function checkIndexedAccessIndexType(type: Type, accessNode: IndexedAccessTypeNode | ElementAccessExpression) { @@ -31254,6 +31441,7 @@ namespace ts { function checkMappedType(node: MappedTypeNode) { checkSourceElement(node.typeParameter); + checkSourceElement(node.nameType); checkSourceElement(node.type); if (!node.type) { @@ -31261,8 +31449,14 @@ namespace ts { } const type = getTypeFromMappedTypeNode(node); - const constraintType = getConstraintTypeFromMappedType(type); - checkTypeAssignableTo(constraintType, keyofConstraintType, getEffectiveConstraintOfTypeParameter(node.typeParameter)); + const nameType = getNameTypeFromMappedType(type); + if (nameType) { + checkTypeAssignableTo(nameType, keyofConstraintType, node.nameType); + } + else { + const constraintType = getConstraintTypeFromMappedType(type); + checkTypeAssignableTo(constraintType, keyofConstraintType, getEffectiveConstraintOfTypeParameter(node.typeParameter)); + } } function checkThisType(node: ThisTypeNode) { @@ -31286,6 +31480,18 @@ namespace ts { registerForUnusedIdentifiersCheck(node); } + function checkTemplateType(node: TemplateLiteralTypeNode) { + forEachChild(node, checkSourceElement); + getTypeFromTypeNode(node); + for (const span of node.templateSpans) { + const type = getTypeFromTypeNode(span.type); + checkTypeAssignableTo(type, templateConstraintType, span.type); + if (!everyType(type, t => !!(t.flags & TypeFlags.Literal) || isGenericIndexType(t))) { + error(span.type, Diagnostics.Template_literal_type_argument_0_is_not_literal_type_or_a_generic_type, typeToString(type)); + } + } + } + function checkImportType(node: ImportTypeNode) { checkSourceElement(node.argument); getTypeFromTypeNode(node); @@ -35897,6 +36103,8 @@ namespace ts { return checkConditionalType(node); case SyntaxKind.InferType: return checkInferType(node); + case SyntaxKind.TemplateLiteralType: + return checkTemplateType(node); case SyntaxKind.ImportType: return checkImportType(node); case SyntaxKind.NamedTupleMember: diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index c793fdc9d19c2..7c90ce2006c6d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3028,6 +3028,10 @@ "category": "Error", "code": 2792 }, + "Template literal type argument '{0}' is not literal type or a generic type.": { + "category": "Error", + "code": 2793 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index fce6e061a2945..f36ce3634c8c8 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1313,6 +1313,8 @@ namespace ts { return emitConstructSignature(node); case SyntaxKind.IndexSignature: return emitIndexSignature(node); + case SyntaxKind.TemplateLiteralTypeSpan: + return emitTemplateTypeSpan(node); // Types case SyntaxKind.TypePredicate: @@ -1357,6 +1359,8 @@ namespace ts { return emitMappedType(node); case SyntaxKind.LiteralType: return emitLiteralType(node); + case SyntaxKind.TemplateLiteralType: + return emitTemplateType(node); case SyntaxKind.ImportType: return emitImportTypeNode(node); case SyntaxKind.JSDocAllType: @@ -2010,6 +2014,20 @@ namespace ts { writeTrailingSemicolon(); } + function emitTemplateTypeSpan(node: TemplateLiteralTypeSpan) { + const keyword = node.casing === TemplateCasing.Uppercase ? "uppercase" : + node.casing === TemplateCasing.Lowercase ? "lowercase" : + node.casing === TemplateCasing.Capitalize ? "capitalize" : + node.casing === TemplateCasing.Uncapitalize ? "uncapitalize" : + undefined; + if (keyword) { + writeKeyword(keyword); + writeSpace(); + } + emit(node.type); + emit(node.literal); + } + function emitSemicolonClassElement() { writeTrailingSemicolon(); } @@ -2202,6 +2220,12 @@ namespace ts { writePunctuation("["); pipelineEmit(EmitHint.MappedTypeParameter, node.typeParameter); + if (node.nameType) { + writeSpace(); + writeKeyword("as"); + writeSpace(); + emit(node.nameType); + } writePunctuation("]"); if (node.questionToken) { @@ -2228,6 +2252,11 @@ namespace ts { emitExpression(node.literal); } + function emitTemplateType(node: TemplateLiteralTypeNode) { + emit(node.head); + emitList(node, node.templateSpans, ListFormat.TemplateExpressionSpans); + } + function emitImportTypeNode(node: ImportTypeNode) { if (node.isTypeOf) { writeKeyword("typeof"); diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index dbe3fd052a484..0e2cf25d28186 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -94,6 +94,8 @@ namespace ts { updateConstructSignature, createIndexSignature, updateIndexSignature, + createTemplateLiteralTypeSpan, + updateTemplateLiteralTypeSpan, createKeywordTypeNode, createTypePredicateNode, updateTypePredicateNode, @@ -138,6 +140,8 @@ namespace ts { updateMappedTypeNode, createLiteralTypeNode, updateLiteralTypeNode, + createTemplateLiteralType, + updateTemplateLiteralType, createObjectBindingPattern, updateObjectBindingPattern, createArrayBindingPattern, @@ -1600,6 +1604,25 @@ namespace ts { : node; } + // @api + function createTemplateLiteralTypeSpan(casing: TemplateCasing, type: TypeNode, literal: TemplateMiddle | TemplateTail) { + const node = createBaseNode(SyntaxKind.TemplateLiteralTypeSpan); + node.casing = casing; + node.type = type; + node.literal = literal; + node.transformFlags = TransformFlags.ContainsTypeScript; + return node; + } + + // @api + function updateTemplateLiteralTypeSpan(casing: TemplateCasing, node: TemplateLiteralTypeSpan, type: TypeNode, literal: TemplateMiddle | TemplateTail) { + return node.casing !== casing + || node.type !== type + || node.literal !== literal + ? update(createTemplateLiteralTypeSpan(casing, type, literal), node) + : node; + } + // // Types // @@ -1891,6 +1914,23 @@ namespace ts { : node; } + // @api + function createTemplateLiteralType(head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]) { + const node = createBaseNode(SyntaxKind.TemplateLiteralType); + node.head = head; + node.templateSpans = createNodeArray(templateSpans); + node.transformFlags = TransformFlags.ContainsTypeScript; + return node; + } + + // @api + function updateTemplateLiteralType(node: TemplateLiteralTypeNode, head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]) { + return node.head !== head + || node.templateSpans !== templateSpans + ? update(createTemplateLiteralType(head, templateSpans), node) + : node; + } + // @api function createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf = false) { const node = createBaseNode(SyntaxKind.ImportType); @@ -1968,10 +2008,11 @@ namespace ts { } // @api - function createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { + function createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { const node = createBaseNode(SyntaxKind.MappedType); node.readonlyToken = readonlyToken; node.typeParameter = typeParameter; + node.nameType = nameType; node.questionToken = questionToken; node.type = type; node.transformFlags = TransformFlags.ContainsTypeScript; @@ -1979,12 +2020,13 @@ namespace ts { } // @api - function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { + function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { return node.readonlyToken !== readonlyToken || node.typeParameter !== typeParameter + || node.nameType !== nameType || node.questionToken !== questionToken || node.type !== type - ? update(createMappedTypeNode(readonlyToken, typeParameter, questionToken, type), node) + ? update(createMappedTypeNode(readonlyToken, typeParameter, nameType, questionToken, type), node) : node; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 4e416c3f79b3b..a2ad539bef319 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -206,6 +206,7 @@ namespace ts { case SyntaxKind.MappedType: return visitNode(cbNode, (node).readonlyToken) || visitNode(cbNode, (node).typeParameter) || + visitNode(cbNode, (node).nameType) || visitNode(cbNode, (node).questionToken) || visitNode(cbNode, (node).type); case SyntaxKind.LiteralType: @@ -424,6 +425,10 @@ namespace ts { return visitNode(cbNode, (node).head) || visitNodes(cbNode, cbNodes, (node).templateSpans); case SyntaxKind.TemplateSpan: return visitNode(cbNode, (node).expression) || visitNode(cbNode, (node).literal); + case SyntaxKind.TemplateLiteralType: + return visitNode(cbNode, (node).head) || visitNodes(cbNode, cbNodes, (node).templateSpans); + case SyntaxKind.TemplateLiteralTypeSpan: + return visitNode(cbNode, (node).type) || visitNode(cbNode, (node).literal); case SyntaxKind.ComputedPropertyName: return visitNode(cbNode, (node).expression); case SyntaxKind.HeritageClause: @@ -2584,6 +2589,49 @@ namespace ts { ); } + function parseTemplateType(): TemplateLiteralTypeNode { + const pos = getNodePos(); + return finishNode( + factory.createTemplateLiteralType( + parseTemplateHead(/*isTaggedTemplate*/ false), + parseTemplateTypeSpans() + ), + pos + ); + } + + function parseTemplateTypeSpans() { + const pos = getNodePos(); + const list = []; + let node: TemplateLiteralTypeSpan; + do { + node = parseTemplateTypeSpan(); + list.push(node); + } + while (node.literal.kind === SyntaxKind.TemplateMiddle); + return createNodeArray(list, pos); + } + + function parseTemplateTypeSpan(): TemplateLiteralTypeSpan { + const pos = getNodePos(); + return finishNode( + factory.createTemplateLiteralTypeSpan( + parseTemplateCasing(), + parseType(), + parseLiteralOfTemplateSpan(/*isTaggedTemplate*/ false) + ), + pos + ); + } + + function parseTemplateCasing(): TemplateCasing { + return parseOptional(SyntaxKind.UppercaseKeyword) ? TemplateCasing.Uppercase : + parseOptional(SyntaxKind.LowercaseKeyword) ? TemplateCasing.Lowercase : + parseOptional(SyntaxKind.CapitalizeKeyword) ? TemplateCasing.Capitalize : + parseOptional(SyntaxKind.UncapitalizeKeyword) ? TemplateCasing.Uncapitalize : + TemplateCasing.None; + } + function parseLiteralOfTemplateSpan(isTaggedTemplate: boolean) { if (token() === SyntaxKind.CloseBraceToken) { reScanTemplateToken(isTaggedTemplate); @@ -3252,6 +3300,7 @@ namespace ts { } parseExpected(SyntaxKind.OpenBracketToken); const typeParameter = parseMappedTypeParameter(); + const nameType = parseOptional(SyntaxKind.AsKeyword) ? parseType() : undefined; parseExpected(SyntaxKind.CloseBracketToken); let questionToken: QuestionToken | PlusToken | MinusToken | undefined; if (token() === SyntaxKind.QuestionToken || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { @@ -3263,7 +3312,7 @@ namespace ts { const type = parseTypeAnnotation(); parseSemicolon(); parseExpected(SyntaxKind.CloseBraceToken); - return finishNode(factory.createMappedTypeNode(readonlyToken, typeParameter, questionToken, type), pos); + return finishNode(factory.createMappedTypeNode(readonlyToken, typeParameter, nameType, questionToken, type), pos); } function parseTupleElementType() { @@ -3444,6 +3493,8 @@ namespace ts { return parseImportType(); case SyntaxKind.AssertsKeyword: return lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine) ? parseAssertsTypePredicate() : parseTypeReference(); + case SyntaxKind.TemplateHead: + return parseTemplateType(); default: return parseTypeReference(); } @@ -3485,6 +3536,8 @@ namespace ts { case SyntaxKind.InferKeyword: case SyntaxKind.ImportKeyword: case SyntaxKind.AssertsKeyword: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: return true; case SyntaxKind.FunctionKeyword: return !inStartOfParameter; diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 77ec82ffef760..5f5248e1073f3 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -151,6 +151,10 @@ namespace ts { yield: SyntaxKind.YieldKeyword, async: SyntaxKind.AsyncKeyword, await: SyntaxKind.AwaitKeyword, + uppercase: SyntaxKind.UppercaseKeyword, + lowercase: SyntaxKind.LowercaseKeyword, + capitalize: SyntaxKind.CapitalizeKeyword, + uncapitalize: SyntaxKind.UncapitalizeKeyword, of: SyntaxKind.OfKeyword, }; @@ -1508,9 +1512,9 @@ namespace ts { } function getIdentifierToken(): SyntaxKind.Identifier | KeywordSyntaxKind { - // Reserved words are between 2 and 11 characters long and start with a lowercase letter + // Reserved words are between 2 and 12 characters long and start with a lowercase letter const len = tokenValue.length; - if (len >= 2 && len <= 11) { + if (len >= 2 && len <= 12) { const ch = tokenValue.charCodeAt(0); if (ch >= CharacterCodes.a && ch <= CharacterCodes.z) { const keyword = textToKeyword.get(tokenValue); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 206250a6f5461..6a9e16eb2a24d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -186,6 +186,10 @@ namespace ts { FromKeyword, GlobalKeyword, BigIntKeyword, + UppercaseKeyword, + LowercaseKeyword, + CapitalizeKeyword, + UncapitalizeKeyword, OfKeyword, // LastKeyword and LastToken and LastContextualKeyword // Parse tree nodes @@ -230,6 +234,8 @@ namespace ts { MappedType, LiteralType, NamedTupleMember, + TemplateLiteralType, + TemplateLiteralTypeSpan, ImportType, // Binding patterns ObjectBindingPattern, @@ -538,6 +544,7 @@ namespace ts { | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword + | SyntaxKind.CapitalizeKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword @@ -570,6 +577,7 @@ namespace ts { | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword + | SyntaxKind.LowercaseKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword @@ -597,9 +605,11 @@ namespace ts { | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword + | SyntaxKind.UncapitalizeKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword + | SyntaxKind.UppercaseKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword @@ -659,6 +669,8 @@ namespace ts { | SyntaxKind.IndexedAccessType | SyntaxKind.MappedType | SyntaxKind.LiteralType + | SyntaxKind.TemplateLiteralType + | SyntaxKind.TemplateLiteralTypeSpan | SyntaxKind.ImportType | SyntaxKind.ExpressionWithTypeArguments | SyntaxKind.JSDocTypeExpression @@ -1622,6 +1634,7 @@ namespace ts { readonly kind: SyntaxKind.MappedType; readonly readonlyToken?: ReadonlyToken | PlusToken | MinusToken; readonly typeParameter: TypeParameterDeclaration; + readonly nameType?: TypeNode; readonly questionToken?: QuestionToken | PlusToken | MinusToken; readonly type?: TypeNode; } @@ -1641,6 +1654,28 @@ namespace ts { export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral; export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; + export interface TemplateLiteralTypeNode extends TypeNode { + kind: SyntaxKind.TemplateLiteralType, + readonly head: TemplateHead; + readonly templateSpans: NodeArray; + } + + export interface TemplateLiteralTypeSpan extends TypeNode { + readonly kind: SyntaxKind.TemplateLiteralTypeSpan, + readonly parent: TemplateLiteralTypeNode; + readonly casing: TemplateCasing; + readonly type: TypeNode; + readonly literal: TemplateMiddle | TemplateTail; + } + + export const enum TemplateCasing { + None, + Uppercase, + Lowercase, + Capitalize, + Uncapitalize, + } + // Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing. // Consider 'Expression'. Without the brand, 'Expression' is actually no different // (structurally) than 'Node'. Because of this you can pass any Node to a function that @@ -2108,21 +2143,21 @@ namespace ts { export interface TemplateHead extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateHead; - readonly parent: TemplateExpression; + readonly parent: TemplateExpression | TemplateLiteralTypeNode; /* @internal */ templateFlags?: TokenFlags; } export interface TemplateMiddle extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateMiddle; - readonly parent: TemplateSpan; + readonly parent: TemplateSpan | TemplateLiteralTypeSpan; /* @internal */ templateFlags?: TokenFlags; } export interface TemplateTail extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateTail; - readonly parent: TemplateSpan; + readonly parent: TemplateSpan | TemplateLiteralTypeSpan; /* @internal */ templateFlags?: TokenFlags; } @@ -4707,7 +4742,7 @@ namespace ts { /* @internal */ export interface MappedSymbol extends TransientSymbol { mappedType: MappedType; - mapper: TypeMapper; + keyType: Type; } /* @internal */ @@ -4849,6 +4884,7 @@ namespace ts { Conditional = 1 << 24, // T extends U ? X : Y Substitution = 1 << 25, // Type parameter substitution NonPrimitive = 1 << 26, // intrinsic object type + TemplateLiteral = 1 << 27, // Template literal type /* @internal */ AnyOrUnknown = Any | Unknown, @@ -4866,7 +4902,7 @@ namespace ts { Intrinsic = Any | Unknown | String | Number | BigInt | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never | NonPrimitive, /* @internal */ Primitive = String | Number | BigInt | Boolean | Enum | EnumLiteral | ESSymbol | Void | Undefined | Null | Literal | UniqueESSymbol, - StringLike = String | StringLiteral, + StringLike = String | StringLiteral | TemplateLiteral, NumberLike = Number | NumberLiteral | Enum, BigIntLike = BigInt | BigIntLiteral, BooleanLike = Boolean | BooleanLiteral, @@ -4879,7 +4915,7 @@ namespace ts { StructuredType = Object | Union | Intersection, TypeVariable = TypeParameter | IndexedAccess, InstantiableNonPrimitive = TypeVariable | Conditional | Substitution, - InstantiablePrimitive = Index, + InstantiablePrimitive = Index | TemplateLiteral, Instantiable = InstantiableNonPrimitive | InstantiablePrimitive, StructuredOrInstantiable = StructuredType | Instantiable, /* @internal */ @@ -4887,7 +4923,7 @@ namespace ts { /* @internal */ Simplifiable = IndexedAccess | Conditional, /* @internal */ - Substructure = Object | Union | Intersection | Index | IndexedAccess | Conditional | Substitution, + Substructure = Object | Union | Intersection | Index | IndexedAccess | Conditional | Substitution | TemplateLiteral, // 'Narrowable' types are types where narrowing actually narrows. // This *should* be every type other than null, undefined, void, and never Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive, @@ -5194,6 +5230,7 @@ namespace ts { declaration: MappedTypeNode; typeParameter?: TypeParameter; constraintType?: Type; + nameType?: Type; templateType?: Type; modifiersType?: Type; resolvedApparentType?: Type; @@ -5334,6 +5371,12 @@ namespace ts { combinedMapper?: TypeMapper; } + export interface TemplateLiteralType extends InstantiableType { + texts: readonly string[]; // Always one element longer than casings/types + casings: readonly TemplateCasing[]; // Always at least one element + types: readonly Type[]; // Always at least one element + } + // Type parameter substitution (TypeFlags.Substitution) // Substitution types are created for type parameters or indexed access types that occur in the // true branch of a conditional type. For example, in 'T extends string ? Foo : Bar', the @@ -6715,6 +6758,8 @@ namespace ts { createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; /* @internal */ createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): IndexSignatureDeclaration; // eslint-disable-line @typescript-eslint/unified-signatures updateIndexSignature(node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + createTemplateLiteralTypeSpan(casing: TemplateCasing, type: TypeNode, literal: TemplateMiddle | TemplateTail): TemplateLiteralTypeSpan; + updateTemplateLiteralTypeSpan(casing: TemplateCasing, node: TemplateLiteralTypeSpan, type: TypeNode, literal: TemplateMiddle | TemplateTail): TemplateLiteralTypeSpan; // // Types @@ -6760,10 +6805,12 @@ namespace ts { updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; - updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode; updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; + createTemplateLiteralType(head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; + updateTemplateLiteralType(node: TemplateLiteralTypeNode, head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; // // Binding Patterns diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts index b2ec665ce8962..899936e5962b4 100644 --- a/src/compiler/visitorPublic.ts +++ b/src/compiler/visitorPublic.ts @@ -565,6 +565,7 @@ namespace ts { return factory.updateMappedTypeNode((node), nodeVisitor((node).readonlyToken, tokenVisitor, isToken), nodeVisitor((node).typeParameter, visitor, isTypeParameterDeclaration), + nodeVisitor((node).nameType, visitor, isTypeNode), nodeVisitor((node).questionToken, tokenVisitor, isToken), nodeVisitor((node).type, visitor, isTypeNode)); diff --git a/src/services/codefixes/convertLiteralTypeToMappedType.ts b/src/services/codefixes/convertLiteralTypeToMappedType.ts index 715c666a95387..4801d8e5f2994 100644 --- a/src/services/codefixes/convertLiteralTypeToMappedType.ts +++ b/src/services/codefixes/convertLiteralTypeToMappedType.ts @@ -48,6 +48,6 @@ namespace ts.codefix { function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { container, typeNode, constraint, name }: Info): void { changes.replaceNode(sourceFile, container, factory.createMappedTypeNode(/*readonlyToken*/ undefined, - factory.createTypeParameterDeclaration(name, factory.createTypeReferenceNode(constraint)), /*questionToken*/ undefined, typeNode)); + factory.createTypeParameterDeclaration(name, factory.createTypeReferenceNode(constraint)), /*nameType*/ undefined, /*questionToken*/ undefined, typeNode)); } } diff --git a/src/services/codefixes/convertToMappedObjectType.ts b/src/services/codefixes/convertToMappedObjectType.ts index 600ef5a1fd86c..687b7318bbe94 100644 --- a/src/services/codefixes/convertToMappedObjectType.ts +++ b/src/services/codefixes/convertToMappedObjectType.ts @@ -44,6 +44,7 @@ namespace ts.codefix { const mappedIntersectionType = factory.createMappedTypeNode( hasEffectiveReadonlyModifier(indexSignature) ? factory.createModifier(SyntaxKind.ReadonlyKeyword) : undefined, mappedTypeParameter, + /*nameType*/ undefined, indexSignature.questionToken, indexSignature.type); const intersectionType = factory.createIntersectionTypeNode([ diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 2474d0c6a0a54..d498dc3ec7e0e 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -259,190 +259,196 @@ declare namespace ts { FromKeyword = 152, GlobalKeyword = 153, BigIntKeyword = 154, - OfKeyword = 155, - QualifiedName = 156, - ComputedPropertyName = 157, - TypeParameter = 158, - Parameter = 159, - Decorator = 160, - PropertySignature = 161, - PropertyDeclaration = 162, - MethodSignature = 163, - MethodDeclaration = 164, - Constructor = 165, - GetAccessor = 166, - SetAccessor = 167, - CallSignature = 168, - ConstructSignature = 169, - IndexSignature = 170, - TypePredicate = 171, - TypeReference = 172, - FunctionType = 173, - ConstructorType = 174, - TypeQuery = 175, - TypeLiteral = 176, - ArrayType = 177, - TupleType = 178, - OptionalType = 179, - RestType = 180, - UnionType = 181, - IntersectionType = 182, - ConditionalType = 183, - InferType = 184, - ParenthesizedType = 185, - ThisType = 186, - TypeOperator = 187, - IndexedAccessType = 188, - MappedType = 189, - LiteralType = 190, - NamedTupleMember = 191, - ImportType = 192, - ObjectBindingPattern = 193, - ArrayBindingPattern = 194, - BindingElement = 195, - ArrayLiteralExpression = 196, - ObjectLiteralExpression = 197, - PropertyAccessExpression = 198, - ElementAccessExpression = 199, - CallExpression = 200, - NewExpression = 201, - TaggedTemplateExpression = 202, - TypeAssertionExpression = 203, - ParenthesizedExpression = 204, - FunctionExpression = 205, - ArrowFunction = 206, - DeleteExpression = 207, - TypeOfExpression = 208, - VoidExpression = 209, - AwaitExpression = 210, - PrefixUnaryExpression = 211, - PostfixUnaryExpression = 212, - BinaryExpression = 213, - ConditionalExpression = 214, - TemplateExpression = 215, - YieldExpression = 216, - SpreadElement = 217, - ClassExpression = 218, - OmittedExpression = 219, - ExpressionWithTypeArguments = 220, - AsExpression = 221, - NonNullExpression = 222, - MetaProperty = 223, - SyntheticExpression = 224, - TemplateSpan = 225, - SemicolonClassElement = 226, - Block = 227, - EmptyStatement = 228, - VariableStatement = 229, - ExpressionStatement = 230, - IfStatement = 231, - DoStatement = 232, - WhileStatement = 233, - ForStatement = 234, - ForInStatement = 235, - ForOfStatement = 236, - ContinueStatement = 237, - BreakStatement = 238, - ReturnStatement = 239, - WithStatement = 240, - SwitchStatement = 241, - LabeledStatement = 242, - ThrowStatement = 243, - TryStatement = 244, - DebuggerStatement = 245, - VariableDeclaration = 246, - VariableDeclarationList = 247, - FunctionDeclaration = 248, - ClassDeclaration = 249, - InterfaceDeclaration = 250, - TypeAliasDeclaration = 251, - EnumDeclaration = 252, - ModuleDeclaration = 253, - ModuleBlock = 254, - CaseBlock = 255, - NamespaceExportDeclaration = 256, - ImportEqualsDeclaration = 257, - ImportDeclaration = 258, - ImportClause = 259, - NamespaceImport = 260, - NamedImports = 261, - ImportSpecifier = 262, - ExportAssignment = 263, - ExportDeclaration = 264, - NamedExports = 265, - NamespaceExport = 266, - ExportSpecifier = 267, - MissingDeclaration = 268, - ExternalModuleReference = 269, - JsxElement = 270, - JsxSelfClosingElement = 271, - JsxOpeningElement = 272, - JsxClosingElement = 273, - JsxFragment = 274, - JsxOpeningFragment = 275, - JsxClosingFragment = 276, - JsxAttribute = 277, - JsxAttributes = 278, - JsxSpreadAttribute = 279, - JsxExpression = 280, - CaseClause = 281, - DefaultClause = 282, - HeritageClause = 283, - CatchClause = 284, - PropertyAssignment = 285, - ShorthandPropertyAssignment = 286, - SpreadAssignment = 287, - EnumMember = 288, - UnparsedPrologue = 289, - UnparsedPrepend = 290, - UnparsedText = 291, - UnparsedInternalText = 292, - UnparsedSyntheticReference = 293, - SourceFile = 294, - Bundle = 295, - UnparsedSource = 296, - InputFiles = 297, - JSDocTypeExpression = 298, - JSDocNameReference = 299, - JSDocAllType = 300, - JSDocUnknownType = 301, - JSDocNullableType = 302, - JSDocNonNullableType = 303, - JSDocOptionalType = 304, - JSDocFunctionType = 305, - JSDocVariadicType = 306, - JSDocNamepathType = 307, - JSDocComment = 308, - JSDocTypeLiteral = 309, - JSDocSignature = 310, - JSDocTag = 311, - JSDocAugmentsTag = 312, - JSDocImplementsTag = 313, - JSDocAuthorTag = 314, - JSDocDeprecatedTag = 315, - JSDocClassTag = 316, - JSDocPublicTag = 317, - JSDocPrivateTag = 318, - JSDocProtectedTag = 319, - JSDocReadonlyTag = 320, - JSDocCallbackTag = 321, - JSDocEnumTag = 322, - JSDocParameterTag = 323, - JSDocReturnTag = 324, - JSDocThisTag = 325, - JSDocTypeTag = 326, - JSDocTemplateTag = 327, - JSDocTypedefTag = 328, - JSDocSeeTag = 329, - JSDocPropertyTag = 330, - SyntaxList = 331, - NotEmittedStatement = 332, - PartiallyEmittedExpression = 333, - CommaListExpression = 334, - MergeDeclarationMarker = 335, - EndOfDeclarationMarker = 336, - SyntheticReferenceExpression = 337, - Count = 338, + UppercaseKeyword = 155, + LowercaseKeyword = 156, + CapitalizeKeyword = 157, + UncapitalizeKeyword = 158, + OfKeyword = 159, + QualifiedName = 160, + ComputedPropertyName = 161, + TypeParameter = 162, + Parameter = 163, + Decorator = 164, + PropertySignature = 165, + PropertyDeclaration = 166, + MethodSignature = 167, + MethodDeclaration = 168, + Constructor = 169, + GetAccessor = 170, + SetAccessor = 171, + CallSignature = 172, + ConstructSignature = 173, + IndexSignature = 174, + TypePredicate = 175, + TypeReference = 176, + FunctionType = 177, + ConstructorType = 178, + TypeQuery = 179, + TypeLiteral = 180, + ArrayType = 181, + TupleType = 182, + OptionalType = 183, + RestType = 184, + UnionType = 185, + IntersectionType = 186, + ConditionalType = 187, + InferType = 188, + ParenthesizedType = 189, + ThisType = 190, + TypeOperator = 191, + IndexedAccessType = 192, + MappedType = 193, + LiteralType = 194, + NamedTupleMember = 195, + TemplateLiteralType = 196, + TemplateLiteralTypeSpan = 197, + ImportType = 198, + ObjectBindingPattern = 199, + ArrayBindingPattern = 200, + BindingElement = 201, + ArrayLiteralExpression = 202, + ObjectLiteralExpression = 203, + PropertyAccessExpression = 204, + ElementAccessExpression = 205, + CallExpression = 206, + NewExpression = 207, + TaggedTemplateExpression = 208, + TypeAssertionExpression = 209, + ParenthesizedExpression = 210, + FunctionExpression = 211, + ArrowFunction = 212, + DeleteExpression = 213, + TypeOfExpression = 214, + VoidExpression = 215, + AwaitExpression = 216, + PrefixUnaryExpression = 217, + PostfixUnaryExpression = 218, + BinaryExpression = 219, + ConditionalExpression = 220, + TemplateExpression = 221, + YieldExpression = 222, + SpreadElement = 223, + ClassExpression = 224, + OmittedExpression = 225, + ExpressionWithTypeArguments = 226, + AsExpression = 227, + NonNullExpression = 228, + MetaProperty = 229, + SyntheticExpression = 230, + TemplateSpan = 231, + SemicolonClassElement = 232, + Block = 233, + EmptyStatement = 234, + VariableStatement = 235, + ExpressionStatement = 236, + IfStatement = 237, + DoStatement = 238, + WhileStatement = 239, + ForStatement = 240, + ForInStatement = 241, + ForOfStatement = 242, + ContinueStatement = 243, + BreakStatement = 244, + ReturnStatement = 245, + WithStatement = 246, + SwitchStatement = 247, + LabeledStatement = 248, + ThrowStatement = 249, + TryStatement = 250, + DebuggerStatement = 251, + VariableDeclaration = 252, + VariableDeclarationList = 253, + FunctionDeclaration = 254, + ClassDeclaration = 255, + InterfaceDeclaration = 256, + TypeAliasDeclaration = 257, + EnumDeclaration = 258, + ModuleDeclaration = 259, + ModuleBlock = 260, + CaseBlock = 261, + NamespaceExportDeclaration = 262, + ImportEqualsDeclaration = 263, + ImportDeclaration = 264, + ImportClause = 265, + NamespaceImport = 266, + NamedImports = 267, + ImportSpecifier = 268, + ExportAssignment = 269, + ExportDeclaration = 270, + NamedExports = 271, + NamespaceExport = 272, + ExportSpecifier = 273, + MissingDeclaration = 274, + ExternalModuleReference = 275, + JsxElement = 276, + JsxSelfClosingElement = 277, + JsxOpeningElement = 278, + JsxClosingElement = 279, + JsxFragment = 280, + JsxOpeningFragment = 281, + JsxClosingFragment = 282, + JsxAttribute = 283, + JsxAttributes = 284, + JsxSpreadAttribute = 285, + JsxExpression = 286, + CaseClause = 287, + DefaultClause = 288, + HeritageClause = 289, + CatchClause = 290, + PropertyAssignment = 291, + ShorthandPropertyAssignment = 292, + SpreadAssignment = 293, + EnumMember = 294, + UnparsedPrologue = 295, + UnparsedPrepend = 296, + UnparsedText = 297, + UnparsedInternalText = 298, + UnparsedSyntheticReference = 299, + SourceFile = 300, + Bundle = 301, + UnparsedSource = 302, + InputFiles = 303, + JSDocTypeExpression = 304, + JSDocNameReference = 305, + JSDocAllType = 306, + JSDocUnknownType = 307, + JSDocNullableType = 308, + JSDocNonNullableType = 309, + JSDocOptionalType = 310, + JSDocFunctionType = 311, + JSDocVariadicType = 312, + JSDocNamepathType = 313, + JSDocComment = 314, + JSDocTypeLiteral = 315, + JSDocSignature = 316, + JSDocTag = 317, + JSDocAugmentsTag = 318, + JSDocImplementsTag = 319, + JSDocAuthorTag = 320, + JSDocDeprecatedTag = 321, + JSDocClassTag = 322, + JSDocPublicTag = 323, + JSDocPrivateTag = 324, + JSDocProtectedTag = 325, + JSDocReadonlyTag = 326, + JSDocCallbackTag = 327, + JSDocEnumTag = 328, + JSDocParameterTag = 329, + JSDocReturnTag = 330, + JSDocThisTag = 331, + JSDocTypeTag = 332, + JSDocTemplateTag = 333, + JSDocTypedefTag = 334, + JSDocSeeTag = 335, + JSDocPropertyTag = 336, + SyntaxList = 337, + NotEmittedStatement = 338, + PartiallyEmittedExpression = 339, + CommaListExpression = 340, + MergeDeclarationMarker = 341, + EndOfDeclarationMarker = 342, + SyntheticReferenceExpression = 343, + Count = 344, FirstAssignment = 62, LastAssignment = 77, FirstCompoundAssignment = 63, @@ -450,15 +456,15 @@ declare namespace ts { FirstReservedWord = 80, LastReservedWord = 115, FirstKeyword = 80, - LastKeyword = 155, + LastKeyword = 159, FirstFutureReservedWord = 116, LastFutureReservedWord = 124, - FirstTypeNode = 171, - LastTypeNode = 192, + FirstTypeNode = 175, + LastTypeNode = 198, FirstPunctuation = 18, LastPunctuation = 77, FirstToken = 0, - LastToken = 155, + LastToken = 159, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -467,19 +473,19 @@ declare namespace ts { LastTemplateToken = 17, FirstBinaryOperator = 29, LastBinaryOperator = 77, - FirstStatement = 229, - LastStatement = 245, - FirstNode = 156, - FirstJSDocNode = 298, - LastJSDocNode = 330, - FirstJSDocTagNode = 311, - LastJSDocTagNode = 330, + FirstStatement = 235, + LastStatement = 251, + FirstNode = 160, + FirstJSDocNode = 304, + LastJSDocNode = 336, + FirstJSDocTagNode = 317, + LastJSDocTagNode = 336, } export type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; export type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; export type PseudoLiteralSyntaxKind = SyntaxKind.TemplateHead | SyntaxKind.TemplateMiddle | SyntaxKind.TemplateTail; export type PunctuationSyntaxKind = SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.OpenParenToken | SyntaxKind.CloseParenToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.DotToken | SyntaxKind.DotDotDotToken | SyntaxKind.SemicolonToken | SyntaxKind.CommaToken | SyntaxKind.QuestionDotToken | SyntaxKind.LessThanToken | SyntaxKind.LessThanSlashToken | SyntaxKind.GreaterThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.EqualsEqualsToken | SyntaxKind.ExclamationEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.EqualsGreaterThanToken | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.AsteriskToken | SyntaxKind.AsteriskAsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken | SyntaxKind.PlusPlusToken | SyntaxKind.MinusMinusToken | SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken | SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken | SyntaxKind.ExclamationToken | SyntaxKind.TildeToken | SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken | SyntaxKind.QuestionToken | SyntaxKind.ColonToken | SyntaxKind.AtToken | SyntaxKind.BacktickToken | SyntaxKind.EqualsToken | SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken; - export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InferKeyword | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.OfKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; + export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CapitalizeKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InferKeyword | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.LowercaseKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.OfKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UncapitalizeKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.UppercaseKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; export type ModifierSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.ConstKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.ExportKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.StaticKeyword; export type KeywordTypeSyntaxKind = SyntaxKind.AnyKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.StringKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VoidKeyword; export type TokenSyntaxKind = SyntaxKind.Unknown | SyntaxKind.EndOfFileToken | TriviaSyntaxKind | LiteralSyntaxKind | PseudoLiteralSyntaxKind | PunctuationSyntaxKind | SyntaxKind.Identifier | KeywordSyntaxKind; @@ -944,6 +950,7 @@ declare namespace ts { readonly kind: SyntaxKind.MappedType; readonly readonlyToken?: ReadonlyToken | PlusToken | MinusToken; readonly typeParameter: TypeParameterDeclaration; + readonly nameType?: TypeNode; readonly questionToken?: QuestionToken | PlusToken | MinusToken; readonly type?: TypeNode; } @@ -956,6 +963,25 @@ declare namespace ts { } export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral; export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; + export interface TemplateLiteralTypeNode extends TypeNode { + kind: SyntaxKind.TemplateLiteralType; + readonly head: TemplateHead; + readonly templateSpans: NodeArray; + } + export interface TemplateLiteralTypeSpan extends TypeNode { + readonly kind: SyntaxKind.TemplateLiteralTypeSpan; + readonly parent: TemplateLiteralTypeNode; + readonly casing: TemplateCasing; + readonly type: TypeNode; + readonly literal: TemplateMiddle | TemplateTail; + } + export enum TemplateCasing { + None = 0, + Uppercase = 1, + Lowercase = 2, + Capitalize = 3, + Uncapitalize = 4 + } export interface Expression extends Node { _expressionBrand: any; } @@ -1144,15 +1170,15 @@ declare namespace ts { export type LiteralToken = NumericLiteral | BigIntLiteral | StringLiteral | JsxText | RegularExpressionLiteral | NoSubstitutionTemplateLiteral; export interface TemplateHead extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateHead; - readonly parent: TemplateExpression; + readonly parent: TemplateExpression | TemplateLiteralTypeNode; } export interface TemplateMiddle extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateMiddle; - readonly parent: TemplateSpan; + readonly parent: TemplateSpan | TemplateLiteralTypeSpan; } export interface TemplateTail extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateTail; - readonly parent: TemplateSpan; + readonly parent: TemplateSpan | TemplateLiteralTypeSpan; } export type PseudoLiteralToken = TemplateHead | TemplateMiddle | TemplateTail; export type TemplateLiteralToken = NoSubstitutionTemplateLiteral | PseudoLiteralToken; @@ -2460,11 +2486,12 @@ declare namespace ts { Conditional = 16777216, Substitution = 33554432, NonPrimitive = 67108864, + TemplateLiteral = 134217728, Literal = 2944, Unit = 109440, StringOrNumberLiteral = 384, PossiblyFalsy = 117724, - StringLike = 132, + StringLike = 134217860, NumberLike = 296, BigIntLike = 2112, BooleanLike = 528, @@ -2475,10 +2502,10 @@ declare namespace ts { StructuredType = 3670016, TypeVariable = 8650752, InstantiableNonPrimitive = 58982400, - InstantiablePrimitive = 4194304, - Instantiable = 63176704, - StructuredOrInstantiable = 66846720, - Narrowable = 133970943, + InstantiablePrimitive = 138412032, + Instantiable = 197394432, + StructuredOrInstantiable = 201064448, + Narrowable = 268188671, } export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; export interface Type { @@ -2629,6 +2656,11 @@ declare namespace ts { resolvedTrueType: Type; resolvedFalseType: Type; } + export interface TemplateLiteralType extends InstantiableType { + texts: readonly string[]; + casings: readonly TemplateCasing[]; + types: readonly Type[]; + } export interface SubstitutionType extends InstantiableType { baseType: Type; substitute: Type; @@ -3186,6 +3218,8 @@ declare namespace ts { updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructSignatureDeclaration; createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; updateIndexSignature(node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + createTemplateLiteralTypeSpan(casing: TemplateCasing, type: TypeNode, literal: TemplateMiddle | TemplateTail): TemplateLiteralTypeSpan; + updateTemplateLiteralTypeSpan(casing: TemplateCasing, node: TemplateLiteralTypeSpan, type: TypeNode, literal: TemplateMiddle | TemplateTail): TemplateLiteralTypeSpan; createKeywordTypeNode(kind: TKind): KeywordTypeNode; createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined): TypePredicateNode; updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined): TypePredicateNode; @@ -3226,10 +3260,12 @@ declare namespace ts { updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; - updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode; updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; + createTemplateLiteralType(head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; + updateTemplateLiteralType(node: TemplateLiteralTypeNode, head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; createObjectBindingPattern(elements: readonly BindingElement[]): ObjectBindingPattern; updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]): ObjectBindingPattern; createArrayBindingPattern(elements: readonly ArrayBindingElement[]): ArrayBindingPattern; @@ -10148,9 +10184,9 @@ declare namespace ts { /** @deprecated Use `factory.updateIndexedAccessTypeNode` or the factory supplied by your transformation context instead. */ const updateIndexedAccessTypeNode: (node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) => IndexedAccessTypeNode; /** @deprecated Use `factory.createMappedTypeNode` or the factory supplied by your transformation context instead. */ - const createMappedTypeNode: (readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined) => MappedTypeNode; + const createMappedTypeNode: (readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined) => MappedTypeNode; /** @deprecated Use `factory.updateMappedTypeNode` or the factory supplied by your transformation context instead. */ - const updateMappedTypeNode: (node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined) => MappedTypeNode; + const updateMappedTypeNode: (node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined) => MappedTypeNode; /** @deprecated Use `factory.createLiteralTypeNode` or the factory supplied by your transformation context instead. */ const createLiteralTypeNode: (literal: LiteralExpression | TrueLiteral | FalseLiteral | PrefixUnaryExpression | NullLiteral) => LiteralTypeNode; /** @deprecated Use `factory.updateLiteralTypeNode` or the factory supplied by your transformation context instead. */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 5ae9c048e4607..9ad992542116d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -259,190 +259,196 @@ declare namespace ts { FromKeyword = 152, GlobalKeyword = 153, BigIntKeyword = 154, - OfKeyword = 155, - QualifiedName = 156, - ComputedPropertyName = 157, - TypeParameter = 158, - Parameter = 159, - Decorator = 160, - PropertySignature = 161, - PropertyDeclaration = 162, - MethodSignature = 163, - MethodDeclaration = 164, - Constructor = 165, - GetAccessor = 166, - SetAccessor = 167, - CallSignature = 168, - ConstructSignature = 169, - IndexSignature = 170, - TypePredicate = 171, - TypeReference = 172, - FunctionType = 173, - ConstructorType = 174, - TypeQuery = 175, - TypeLiteral = 176, - ArrayType = 177, - TupleType = 178, - OptionalType = 179, - RestType = 180, - UnionType = 181, - IntersectionType = 182, - ConditionalType = 183, - InferType = 184, - ParenthesizedType = 185, - ThisType = 186, - TypeOperator = 187, - IndexedAccessType = 188, - MappedType = 189, - LiteralType = 190, - NamedTupleMember = 191, - ImportType = 192, - ObjectBindingPattern = 193, - ArrayBindingPattern = 194, - BindingElement = 195, - ArrayLiteralExpression = 196, - ObjectLiteralExpression = 197, - PropertyAccessExpression = 198, - ElementAccessExpression = 199, - CallExpression = 200, - NewExpression = 201, - TaggedTemplateExpression = 202, - TypeAssertionExpression = 203, - ParenthesizedExpression = 204, - FunctionExpression = 205, - ArrowFunction = 206, - DeleteExpression = 207, - TypeOfExpression = 208, - VoidExpression = 209, - AwaitExpression = 210, - PrefixUnaryExpression = 211, - PostfixUnaryExpression = 212, - BinaryExpression = 213, - ConditionalExpression = 214, - TemplateExpression = 215, - YieldExpression = 216, - SpreadElement = 217, - ClassExpression = 218, - OmittedExpression = 219, - ExpressionWithTypeArguments = 220, - AsExpression = 221, - NonNullExpression = 222, - MetaProperty = 223, - SyntheticExpression = 224, - TemplateSpan = 225, - SemicolonClassElement = 226, - Block = 227, - EmptyStatement = 228, - VariableStatement = 229, - ExpressionStatement = 230, - IfStatement = 231, - DoStatement = 232, - WhileStatement = 233, - ForStatement = 234, - ForInStatement = 235, - ForOfStatement = 236, - ContinueStatement = 237, - BreakStatement = 238, - ReturnStatement = 239, - WithStatement = 240, - SwitchStatement = 241, - LabeledStatement = 242, - ThrowStatement = 243, - TryStatement = 244, - DebuggerStatement = 245, - VariableDeclaration = 246, - VariableDeclarationList = 247, - FunctionDeclaration = 248, - ClassDeclaration = 249, - InterfaceDeclaration = 250, - TypeAliasDeclaration = 251, - EnumDeclaration = 252, - ModuleDeclaration = 253, - ModuleBlock = 254, - CaseBlock = 255, - NamespaceExportDeclaration = 256, - ImportEqualsDeclaration = 257, - ImportDeclaration = 258, - ImportClause = 259, - NamespaceImport = 260, - NamedImports = 261, - ImportSpecifier = 262, - ExportAssignment = 263, - ExportDeclaration = 264, - NamedExports = 265, - NamespaceExport = 266, - ExportSpecifier = 267, - MissingDeclaration = 268, - ExternalModuleReference = 269, - JsxElement = 270, - JsxSelfClosingElement = 271, - JsxOpeningElement = 272, - JsxClosingElement = 273, - JsxFragment = 274, - JsxOpeningFragment = 275, - JsxClosingFragment = 276, - JsxAttribute = 277, - JsxAttributes = 278, - JsxSpreadAttribute = 279, - JsxExpression = 280, - CaseClause = 281, - DefaultClause = 282, - HeritageClause = 283, - CatchClause = 284, - PropertyAssignment = 285, - ShorthandPropertyAssignment = 286, - SpreadAssignment = 287, - EnumMember = 288, - UnparsedPrologue = 289, - UnparsedPrepend = 290, - UnparsedText = 291, - UnparsedInternalText = 292, - UnparsedSyntheticReference = 293, - SourceFile = 294, - Bundle = 295, - UnparsedSource = 296, - InputFiles = 297, - JSDocTypeExpression = 298, - JSDocNameReference = 299, - JSDocAllType = 300, - JSDocUnknownType = 301, - JSDocNullableType = 302, - JSDocNonNullableType = 303, - JSDocOptionalType = 304, - JSDocFunctionType = 305, - JSDocVariadicType = 306, - JSDocNamepathType = 307, - JSDocComment = 308, - JSDocTypeLiteral = 309, - JSDocSignature = 310, - JSDocTag = 311, - JSDocAugmentsTag = 312, - JSDocImplementsTag = 313, - JSDocAuthorTag = 314, - JSDocDeprecatedTag = 315, - JSDocClassTag = 316, - JSDocPublicTag = 317, - JSDocPrivateTag = 318, - JSDocProtectedTag = 319, - JSDocReadonlyTag = 320, - JSDocCallbackTag = 321, - JSDocEnumTag = 322, - JSDocParameterTag = 323, - JSDocReturnTag = 324, - JSDocThisTag = 325, - JSDocTypeTag = 326, - JSDocTemplateTag = 327, - JSDocTypedefTag = 328, - JSDocSeeTag = 329, - JSDocPropertyTag = 330, - SyntaxList = 331, - NotEmittedStatement = 332, - PartiallyEmittedExpression = 333, - CommaListExpression = 334, - MergeDeclarationMarker = 335, - EndOfDeclarationMarker = 336, - SyntheticReferenceExpression = 337, - Count = 338, + UppercaseKeyword = 155, + LowercaseKeyword = 156, + CapitalizeKeyword = 157, + UncapitalizeKeyword = 158, + OfKeyword = 159, + QualifiedName = 160, + ComputedPropertyName = 161, + TypeParameter = 162, + Parameter = 163, + Decorator = 164, + PropertySignature = 165, + PropertyDeclaration = 166, + MethodSignature = 167, + MethodDeclaration = 168, + Constructor = 169, + GetAccessor = 170, + SetAccessor = 171, + CallSignature = 172, + ConstructSignature = 173, + IndexSignature = 174, + TypePredicate = 175, + TypeReference = 176, + FunctionType = 177, + ConstructorType = 178, + TypeQuery = 179, + TypeLiteral = 180, + ArrayType = 181, + TupleType = 182, + OptionalType = 183, + RestType = 184, + UnionType = 185, + IntersectionType = 186, + ConditionalType = 187, + InferType = 188, + ParenthesizedType = 189, + ThisType = 190, + TypeOperator = 191, + IndexedAccessType = 192, + MappedType = 193, + LiteralType = 194, + NamedTupleMember = 195, + TemplateLiteralType = 196, + TemplateLiteralTypeSpan = 197, + ImportType = 198, + ObjectBindingPattern = 199, + ArrayBindingPattern = 200, + BindingElement = 201, + ArrayLiteralExpression = 202, + ObjectLiteralExpression = 203, + PropertyAccessExpression = 204, + ElementAccessExpression = 205, + CallExpression = 206, + NewExpression = 207, + TaggedTemplateExpression = 208, + TypeAssertionExpression = 209, + ParenthesizedExpression = 210, + FunctionExpression = 211, + ArrowFunction = 212, + DeleteExpression = 213, + TypeOfExpression = 214, + VoidExpression = 215, + AwaitExpression = 216, + PrefixUnaryExpression = 217, + PostfixUnaryExpression = 218, + BinaryExpression = 219, + ConditionalExpression = 220, + TemplateExpression = 221, + YieldExpression = 222, + SpreadElement = 223, + ClassExpression = 224, + OmittedExpression = 225, + ExpressionWithTypeArguments = 226, + AsExpression = 227, + NonNullExpression = 228, + MetaProperty = 229, + SyntheticExpression = 230, + TemplateSpan = 231, + SemicolonClassElement = 232, + Block = 233, + EmptyStatement = 234, + VariableStatement = 235, + ExpressionStatement = 236, + IfStatement = 237, + DoStatement = 238, + WhileStatement = 239, + ForStatement = 240, + ForInStatement = 241, + ForOfStatement = 242, + ContinueStatement = 243, + BreakStatement = 244, + ReturnStatement = 245, + WithStatement = 246, + SwitchStatement = 247, + LabeledStatement = 248, + ThrowStatement = 249, + TryStatement = 250, + DebuggerStatement = 251, + VariableDeclaration = 252, + VariableDeclarationList = 253, + FunctionDeclaration = 254, + ClassDeclaration = 255, + InterfaceDeclaration = 256, + TypeAliasDeclaration = 257, + EnumDeclaration = 258, + ModuleDeclaration = 259, + ModuleBlock = 260, + CaseBlock = 261, + NamespaceExportDeclaration = 262, + ImportEqualsDeclaration = 263, + ImportDeclaration = 264, + ImportClause = 265, + NamespaceImport = 266, + NamedImports = 267, + ImportSpecifier = 268, + ExportAssignment = 269, + ExportDeclaration = 270, + NamedExports = 271, + NamespaceExport = 272, + ExportSpecifier = 273, + MissingDeclaration = 274, + ExternalModuleReference = 275, + JsxElement = 276, + JsxSelfClosingElement = 277, + JsxOpeningElement = 278, + JsxClosingElement = 279, + JsxFragment = 280, + JsxOpeningFragment = 281, + JsxClosingFragment = 282, + JsxAttribute = 283, + JsxAttributes = 284, + JsxSpreadAttribute = 285, + JsxExpression = 286, + CaseClause = 287, + DefaultClause = 288, + HeritageClause = 289, + CatchClause = 290, + PropertyAssignment = 291, + ShorthandPropertyAssignment = 292, + SpreadAssignment = 293, + EnumMember = 294, + UnparsedPrologue = 295, + UnparsedPrepend = 296, + UnparsedText = 297, + UnparsedInternalText = 298, + UnparsedSyntheticReference = 299, + SourceFile = 300, + Bundle = 301, + UnparsedSource = 302, + InputFiles = 303, + JSDocTypeExpression = 304, + JSDocNameReference = 305, + JSDocAllType = 306, + JSDocUnknownType = 307, + JSDocNullableType = 308, + JSDocNonNullableType = 309, + JSDocOptionalType = 310, + JSDocFunctionType = 311, + JSDocVariadicType = 312, + JSDocNamepathType = 313, + JSDocComment = 314, + JSDocTypeLiteral = 315, + JSDocSignature = 316, + JSDocTag = 317, + JSDocAugmentsTag = 318, + JSDocImplementsTag = 319, + JSDocAuthorTag = 320, + JSDocDeprecatedTag = 321, + JSDocClassTag = 322, + JSDocPublicTag = 323, + JSDocPrivateTag = 324, + JSDocProtectedTag = 325, + JSDocReadonlyTag = 326, + JSDocCallbackTag = 327, + JSDocEnumTag = 328, + JSDocParameterTag = 329, + JSDocReturnTag = 330, + JSDocThisTag = 331, + JSDocTypeTag = 332, + JSDocTemplateTag = 333, + JSDocTypedefTag = 334, + JSDocSeeTag = 335, + JSDocPropertyTag = 336, + SyntaxList = 337, + NotEmittedStatement = 338, + PartiallyEmittedExpression = 339, + CommaListExpression = 340, + MergeDeclarationMarker = 341, + EndOfDeclarationMarker = 342, + SyntheticReferenceExpression = 343, + Count = 344, FirstAssignment = 62, LastAssignment = 77, FirstCompoundAssignment = 63, @@ -450,15 +456,15 @@ declare namespace ts { FirstReservedWord = 80, LastReservedWord = 115, FirstKeyword = 80, - LastKeyword = 155, + LastKeyword = 159, FirstFutureReservedWord = 116, LastFutureReservedWord = 124, - FirstTypeNode = 171, - LastTypeNode = 192, + FirstTypeNode = 175, + LastTypeNode = 198, FirstPunctuation = 18, LastPunctuation = 77, FirstToken = 0, - LastToken = 155, + LastToken = 159, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -467,19 +473,19 @@ declare namespace ts { LastTemplateToken = 17, FirstBinaryOperator = 29, LastBinaryOperator = 77, - FirstStatement = 229, - LastStatement = 245, - FirstNode = 156, - FirstJSDocNode = 298, - LastJSDocNode = 330, - FirstJSDocTagNode = 311, - LastJSDocTagNode = 330, + FirstStatement = 235, + LastStatement = 251, + FirstNode = 160, + FirstJSDocNode = 304, + LastJSDocNode = 336, + FirstJSDocTagNode = 317, + LastJSDocTagNode = 336, } export type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; export type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; export type PseudoLiteralSyntaxKind = SyntaxKind.TemplateHead | SyntaxKind.TemplateMiddle | SyntaxKind.TemplateTail; export type PunctuationSyntaxKind = SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.OpenParenToken | SyntaxKind.CloseParenToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.DotToken | SyntaxKind.DotDotDotToken | SyntaxKind.SemicolonToken | SyntaxKind.CommaToken | SyntaxKind.QuestionDotToken | SyntaxKind.LessThanToken | SyntaxKind.LessThanSlashToken | SyntaxKind.GreaterThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.EqualsEqualsToken | SyntaxKind.ExclamationEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.EqualsGreaterThanToken | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.AsteriskToken | SyntaxKind.AsteriskAsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken | SyntaxKind.PlusPlusToken | SyntaxKind.MinusMinusToken | SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken | SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken | SyntaxKind.ExclamationToken | SyntaxKind.TildeToken | SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken | SyntaxKind.QuestionToken | SyntaxKind.ColonToken | SyntaxKind.AtToken | SyntaxKind.BacktickToken | SyntaxKind.EqualsToken | SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken; - export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InferKeyword | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.OfKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; + export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CapitalizeKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InferKeyword | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.LowercaseKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.OfKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UncapitalizeKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.UppercaseKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; export type ModifierSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.ConstKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.ExportKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.StaticKeyword; export type KeywordTypeSyntaxKind = SyntaxKind.AnyKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.StringKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VoidKeyword; export type TokenSyntaxKind = SyntaxKind.Unknown | SyntaxKind.EndOfFileToken | TriviaSyntaxKind | LiteralSyntaxKind | PseudoLiteralSyntaxKind | PunctuationSyntaxKind | SyntaxKind.Identifier | KeywordSyntaxKind; @@ -944,6 +950,7 @@ declare namespace ts { readonly kind: SyntaxKind.MappedType; readonly readonlyToken?: ReadonlyToken | PlusToken | MinusToken; readonly typeParameter: TypeParameterDeclaration; + readonly nameType?: TypeNode; readonly questionToken?: QuestionToken | PlusToken | MinusToken; readonly type?: TypeNode; } @@ -956,6 +963,25 @@ declare namespace ts { } export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral; export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; + export interface TemplateLiteralTypeNode extends TypeNode { + kind: SyntaxKind.TemplateLiteralType; + readonly head: TemplateHead; + readonly templateSpans: NodeArray; + } + export interface TemplateLiteralTypeSpan extends TypeNode { + readonly kind: SyntaxKind.TemplateLiteralTypeSpan; + readonly parent: TemplateLiteralTypeNode; + readonly casing: TemplateCasing; + readonly type: TypeNode; + readonly literal: TemplateMiddle | TemplateTail; + } + export enum TemplateCasing { + None = 0, + Uppercase = 1, + Lowercase = 2, + Capitalize = 3, + Uncapitalize = 4 + } export interface Expression extends Node { _expressionBrand: any; } @@ -1144,15 +1170,15 @@ declare namespace ts { export type LiteralToken = NumericLiteral | BigIntLiteral | StringLiteral | JsxText | RegularExpressionLiteral | NoSubstitutionTemplateLiteral; export interface TemplateHead extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateHead; - readonly parent: TemplateExpression; + readonly parent: TemplateExpression | TemplateLiteralTypeNode; } export interface TemplateMiddle extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateMiddle; - readonly parent: TemplateSpan; + readonly parent: TemplateSpan | TemplateLiteralTypeSpan; } export interface TemplateTail extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateTail; - readonly parent: TemplateSpan; + readonly parent: TemplateSpan | TemplateLiteralTypeSpan; } export type PseudoLiteralToken = TemplateHead | TemplateMiddle | TemplateTail; export type TemplateLiteralToken = NoSubstitutionTemplateLiteral | PseudoLiteralToken; @@ -2460,11 +2486,12 @@ declare namespace ts { Conditional = 16777216, Substitution = 33554432, NonPrimitive = 67108864, + TemplateLiteral = 134217728, Literal = 2944, Unit = 109440, StringOrNumberLiteral = 384, PossiblyFalsy = 117724, - StringLike = 132, + StringLike = 134217860, NumberLike = 296, BigIntLike = 2112, BooleanLike = 528, @@ -2475,10 +2502,10 @@ declare namespace ts { StructuredType = 3670016, TypeVariable = 8650752, InstantiableNonPrimitive = 58982400, - InstantiablePrimitive = 4194304, - Instantiable = 63176704, - StructuredOrInstantiable = 66846720, - Narrowable = 133970943, + InstantiablePrimitive = 138412032, + Instantiable = 197394432, + StructuredOrInstantiable = 201064448, + Narrowable = 268188671, } export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; export interface Type { @@ -2629,6 +2656,11 @@ declare namespace ts { resolvedTrueType: Type; resolvedFalseType: Type; } + export interface TemplateLiteralType extends InstantiableType { + texts: readonly string[]; + casings: readonly TemplateCasing[]; + types: readonly Type[]; + } export interface SubstitutionType extends InstantiableType { baseType: Type; substitute: Type; @@ -3186,6 +3218,8 @@ declare namespace ts { updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructSignatureDeclaration; createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; updateIndexSignature(node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + createTemplateLiteralTypeSpan(casing: TemplateCasing, type: TypeNode, literal: TemplateMiddle | TemplateTail): TemplateLiteralTypeSpan; + updateTemplateLiteralTypeSpan(casing: TemplateCasing, node: TemplateLiteralTypeSpan, type: TypeNode, literal: TemplateMiddle | TemplateTail): TemplateLiteralTypeSpan; createKeywordTypeNode(kind: TKind): KeywordTypeNode; createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined): TypePredicateNode; updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined): TypePredicateNode; @@ -3226,10 +3260,12 @@ declare namespace ts { updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; - updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode; updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; + createTemplateLiteralType(head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; + updateTemplateLiteralType(node: TemplateLiteralTypeNode, head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; createObjectBindingPattern(elements: readonly BindingElement[]): ObjectBindingPattern; updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]): ObjectBindingPattern; createArrayBindingPattern(elements: readonly ArrayBindingElement[]): ArrayBindingPattern; @@ -6528,9 +6564,9 @@ declare namespace ts { /** @deprecated Use `factory.updateIndexedAccessTypeNode` or the factory supplied by your transformation context instead. */ const updateIndexedAccessTypeNode: (node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) => IndexedAccessTypeNode; /** @deprecated Use `factory.createMappedTypeNode` or the factory supplied by your transformation context instead. */ - const createMappedTypeNode: (readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined) => MappedTypeNode; + const createMappedTypeNode: (readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined) => MappedTypeNode; /** @deprecated Use `factory.updateMappedTypeNode` or the factory supplied by your transformation context instead. */ - const updateMappedTypeNode: (node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined) => MappedTypeNode; + const updateMappedTypeNode: (node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined) => MappedTypeNode; /** @deprecated Use `factory.createLiteralTypeNode` or the factory supplied by your transformation context instead. */ const createLiteralTypeNode: (literal: LiteralExpression | TrueLiteral | FalseLiteral | PrefixUnaryExpression | NullLiteral) => LiteralTypeNode; /** @deprecated Use `factory.updateLiteralTypeNode` or the factory supplied by your transformation context instead. */ diff --git a/tests/baselines/reference/complicatedIndexesOfIntersectionsAreInferencable.types b/tests/baselines/reference/complicatedIndexesOfIntersectionsAreInferencable.types index c10b5aa4f8e7c..2460b5407efae 100644 --- a/tests/baselines/reference/complicatedIndexesOfIntersectionsAreInferencable.types +++ b/tests/baselines/reference/complicatedIndexesOfIntersectionsAreInferencable.types @@ -15,7 +15,7 @@ declare function Func( >Func : (x: (string extends "validate" | "initialValues" | keyof ExtraProps ? Readonly & ExtraProps> : Pick & ExtraProps>, "validate" | "initialValues" | Exclude> & Partial & ExtraProps>, "validateOnChange" | Extract>>)) => void x: (string extends "validate" | "initialValues" | keyof ExtraProps ->x : string extends keyof ExtraProps | "validate" | "initialValues" ? Readonly & ExtraProps> : Pick & ExtraProps>, Exclude | "validate" | "initialValues"> & Partial & ExtraProps>, "validateOnChange" | Extract>> +>x : string extends "validate" | "initialValues" | keyof ExtraProps ? Readonly & ExtraProps> : Pick & ExtraProps>, "validate" | "initialValues" | Exclude> & Partial & ExtraProps>, "validateOnChange" | Extract>> ? Readonly & ExtraProps> : Pick & ExtraProps>, "validate" | "initialValues" | Exclude> @@ -24,7 +24,7 @@ declare function Func( Func({ >Func({ initialValues: { foo: "" }, validate: props => { props.foo; }}) : void ->Func : (x: string extends keyof ExtraProps | "validate" | "initialValues" ? Readonly & ExtraProps> : Pick & ExtraProps>, Exclude | "validate" | "initialValues"> & Partial & ExtraProps>, "validateOnChange" | Extract>>) => void +>Func : (x: string extends "validate" | "initialValues" | keyof ExtraProps ? Readonly & ExtraProps> : Pick & ExtraProps>, "validate" | "initialValues" | Exclude> & Partial & ExtraProps>, "validateOnChange" | Extract>>) => void >{ initialValues: { foo: "" }, validate: props => { props.foo; }} : { initialValues: { foo: string; }; validate: (props: { foo: string; }) => void; } initialValues: { diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types index 97750450fde67..e0b3e13ed60b4 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.types +++ b/tests/baselines/reference/keyofAndIndexedAccess.types @@ -125,7 +125,7 @@ type NAME = "name"; >NAME : "name" type WIDTH_OR_HEIGHT = "width" | "height"; ->WIDTH_OR_HEIGHT : "width" | "height" +>WIDTH_OR_HEIGHT : WIDTH_OR_HEIGHT type Q10 = Shape["name"]; // string >Q10 : string @@ -225,7 +225,7 @@ function f10(shape: Shape) { >getProperty(shape, cond ? "width" : "height") : number >getProperty : (obj: T, key: K) => T[K] >shape : Shape ->cond ? "width" : "height" : "width" | "height" +>cond ? "width" : "height" : WIDTH_OR_HEIGHT >cond : boolean >"width" : "width" >"height" : "height" @@ -251,7 +251,7 @@ function f10(shape: Shape) { >setProperty(shape, cond ? "width" : "height", 10) : void >setProperty : (obj: T, key: K, value: T[K]) => void >shape : Shape ->cond ? "width" : "height" : "width" | "height" +>cond ? "width" : "height" : WIDTH_OR_HEIGHT >cond : boolean >"width" : "width" >"height" : "height" @@ -391,7 +391,7 @@ function f20(component: Component) { >component.getProperty : (key: K) => Shape[K] >component : Component >getProperty : (key: K) => Shape[K] ->cond ? "width" : "height" : "width" | "height" +>cond ? "width" : "height" : WIDTH_OR_HEIGHT >cond : boolean >"width" : "width" >"height" : "height" @@ -420,7 +420,7 @@ function f20(component: Component) { >component.setProperty : (key: K, value: Shape[K]) => void >component : Component >setProperty : (key: K, value: Shape[K]) => void ->cond ? "width" : "height" : "width" | "height" +>cond ? "width" : "height" : WIDTH_OR_HEIGHT >cond : boolean >"width" : "width" >"height" : "height" @@ -507,7 +507,7 @@ function f31(key: K) { } function f32(key: K) { ->f32 : (key: K) => Shape[K] +>f32 : (key: K) => Shape[K] >key : K const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; diff --git a/tests/baselines/reference/lateBoundConstraintTypeChecksCorrectly.types b/tests/baselines/reference/lateBoundConstraintTypeChecksCorrectly.types index fa806eda9641c..6cde47ff0dc04 100644 --- a/tests/baselines/reference/lateBoundConstraintTypeChecksCorrectly.types +++ b/tests/baselines/reference/lateBoundConstraintTypeChecksCorrectly.types @@ -6,7 +6,7 @@ declare const barProp: unique symbol; >barProp : unique symbol type BothProps = typeof fooProp | typeof barProp; ->BothProps : unique symbol | unique symbol +>BothProps : BothProps >fooProp : unique symbol >barProp : unique symbol diff --git a/tests/baselines/reference/mappedTypeAsClauses.js b/tests/baselines/reference/mappedTypeAsClauses.js new file mode 100644 index 0000000000000..75c1d32cd60ae --- /dev/null +++ b/tests/baselines/reference/mappedTypeAsClauses.js @@ -0,0 +1,84 @@ +//// [mappedTypeAsClauses.ts] +// Mapped type 'as N' clauses + +type Getters = { [P in keyof T & string as `get${capitalize P}`]: () => T[P] }; +type TG1 = Getters<{ foo: string, bar: number, baz: { z: boolean } }>; + +// Mapped type with 'as N' clause has no constraint on 'in T' clause + +type PropDef = { name: K, type: T }; + +type TypeFromDefs> = { [P in T as P['name']]: P['type'] }; + +type TP1 = TypeFromDefs<{ name: 'a', type: string } | { name: 'b', type: number } | { name: 'a', type: boolean }>; + +// No array or tuple type mapping when 'as N' clause present + +type TA1 = Getters; +type TA2 = Getters<[number, boolean]>; + +// Filtering using 'as N' clause + +type Methods = { [P in keyof T as T[P] extends Function ? P : never]: T[P] }; +type TM1 = Methods<{ foo(): number, bar(x: string): boolean, baz: string | number }>; + +// Mapping to multiple names using 'as N' clause + +type DoubleProp = { [P in keyof T & string as `${P}1` | `${P}2`]: T[P] } +type TD1 = DoubleProp<{ a: string, b: number }>; // { a1: string, a2: string, b1: number, b2: number } +type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2' +type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & string}2` + + +//// [mappedTypeAsClauses.js] +"use strict"; +// Mapped type 'as N' clauses + + +//// [mappedTypeAsClauses.d.ts] +declare type Getters = { + [P in keyof T & string as `get${capitalize P}`]: () => T[P]; +}; +declare type TG1 = Getters<{ + foo: string; + bar: number; + baz: { + z: boolean; + }; +}>; +declare type PropDef = { + name: K; + type: T; +}; +declare type TypeFromDefs> = { + [P in T as P['name']]: P['type']; +}; +declare type TP1 = TypeFromDefs<{ + name: 'a'; + type: string; +} | { + name: 'b'; + type: number; +} | { + name: 'a'; + type: boolean; +}>; +declare type TA1 = Getters; +declare type TA2 = Getters<[number, boolean]>; +declare type Methods = { + [P in keyof T as T[P] extends Function ? P : never]: T[P]; +}; +declare type TM1 = Methods<{ + foo(): number; + bar(x: string): boolean; + baz: string | number; +}>; +declare type DoubleProp = { + [P in keyof T & string as `${P}1` | `${P}2`]: T[P]; +}; +declare type TD1 = DoubleProp<{ + a: string; + b: number; +}>; +declare type TD2 = keyof TD1; +declare type TD3 = keyof DoubleProp; diff --git a/tests/baselines/reference/mappedTypeAsClauses.symbols b/tests/baselines/reference/mappedTypeAsClauses.symbols new file mode 100644 index 0000000000000..75768ce31af90 --- /dev/null +++ b/tests/baselines/reference/mappedTypeAsClauses.symbols @@ -0,0 +1,110 @@ +=== tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts === +// Mapped type 'as N' clauses + +type Getters = { [P in keyof T & string as `get${capitalize P}`]: () => T[P] }; +>Getters : Symbol(Getters, Decl(mappedTypeAsClauses.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 2, 13)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 2, 21)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 2, 13)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 2, 21)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 2, 13)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 2, 21)) + +type TG1 = Getters<{ foo: string, bar: number, baz: { z: boolean } }>; +>TG1 : Symbol(TG1, Decl(mappedTypeAsClauses.ts, 2, 82)) +>Getters : Symbol(Getters, Decl(mappedTypeAsClauses.ts, 0, 0)) +>foo : Symbol(foo, Decl(mappedTypeAsClauses.ts, 3, 20)) +>bar : Symbol(bar, Decl(mappedTypeAsClauses.ts, 3, 33)) +>baz : Symbol(baz, Decl(mappedTypeAsClauses.ts, 3, 46)) +>z : Symbol(z, Decl(mappedTypeAsClauses.ts, 3, 53)) + +// Mapped type with 'as N' clause has no constraint on 'in T' clause + +type PropDef = { name: K, type: T }; +>PropDef : Symbol(PropDef, Decl(mappedTypeAsClauses.ts, 3, 70)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 7, 13)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 7, 33)) +>name : Symbol(name, Decl(mappedTypeAsClauses.ts, 7, 40)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 7, 13)) +>type : Symbol(type, Decl(mappedTypeAsClauses.ts, 7, 49)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 7, 33)) + +type TypeFromDefs> = { [P in T as P['name']]: P['type'] }; +>TypeFromDefs : Symbol(TypeFromDefs, Decl(mappedTypeAsClauses.ts, 7, 60)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 9, 18)) +>PropDef : Symbol(PropDef, Decl(mappedTypeAsClauses.ts, 3, 70)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 9, 58)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 9, 18)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 9, 58)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 9, 58)) + +type TP1 = TypeFromDefs<{ name: 'a', type: string } | { name: 'b', type: number } | { name: 'a', type: boolean }>; +>TP1 : Symbol(TP1, Decl(mappedTypeAsClauses.ts, 9, 92)) +>TypeFromDefs : Symbol(TypeFromDefs, Decl(mappedTypeAsClauses.ts, 7, 60)) +>name : Symbol(name, Decl(mappedTypeAsClauses.ts, 11, 25)) +>type : Symbol(type, Decl(mappedTypeAsClauses.ts, 11, 36)) +>name : Symbol(name, Decl(mappedTypeAsClauses.ts, 11, 55)) +>type : Symbol(type, Decl(mappedTypeAsClauses.ts, 11, 66)) +>name : Symbol(name, Decl(mappedTypeAsClauses.ts, 11, 85)) +>type : Symbol(type, Decl(mappedTypeAsClauses.ts, 11, 96)) + +// No array or tuple type mapping when 'as N' clause present + +type TA1 = Getters; +>TA1 : Symbol(TA1, Decl(mappedTypeAsClauses.ts, 11, 114)) +>Getters : Symbol(Getters, Decl(mappedTypeAsClauses.ts, 0, 0)) + +type TA2 = Getters<[number, boolean]>; +>TA2 : Symbol(TA2, Decl(mappedTypeAsClauses.ts, 15, 29)) +>Getters : Symbol(Getters, Decl(mappedTypeAsClauses.ts, 0, 0)) + +// Filtering using 'as N' clause + +type Methods = { [P in keyof T as T[P] extends Function ? P : never]: T[P] }; +>Methods : Symbol(Methods, Decl(mappedTypeAsClauses.ts, 16, 38)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 20, 13)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 20, 21)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 20, 13)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 20, 13)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 20, 21)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 20, 21)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 20, 13)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 20, 21)) + +type TM1 = Methods<{ foo(): number, bar(x: string): boolean, baz: string | number }>; +>TM1 : Symbol(TM1, Decl(mappedTypeAsClauses.ts, 20, 80)) +>Methods : Symbol(Methods, Decl(mappedTypeAsClauses.ts, 16, 38)) +>foo : Symbol(foo, Decl(mappedTypeAsClauses.ts, 21, 20)) +>bar : Symbol(bar, Decl(mappedTypeAsClauses.ts, 21, 35)) +>x : Symbol(x, Decl(mappedTypeAsClauses.ts, 21, 40)) +>baz : Symbol(baz, Decl(mappedTypeAsClauses.ts, 21, 60)) + +// Mapping to multiple names using 'as N' clause + +type DoubleProp = { [P in keyof T & string as `${P}1` | `${P}2`]: T[P] } +>DoubleProp : Symbol(DoubleProp, Decl(mappedTypeAsClauses.ts, 21, 85)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 25, 16)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 25, 24)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 25, 16)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 25, 24)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 25, 24)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 25, 16)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 25, 24)) + +type TD1 = DoubleProp<{ a: string, b: number }>; // { a1: string, a2: string, b1: number, b2: number } +>TD1 : Symbol(TD1, Decl(mappedTypeAsClauses.ts, 25, 75)) +>DoubleProp : Symbol(DoubleProp, Decl(mappedTypeAsClauses.ts, 21, 85)) +>a : Symbol(a, Decl(mappedTypeAsClauses.ts, 26, 23)) +>b : Symbol(b, Decl(mappedTypeAsClauses.ts, 26, 34)) + +type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2' +>TD2 : Symbol(TD2, Decl(mappedTypeAsClauses.ts, 26, 48)) +>TD1 : Symbol(TD1, Decl(mappedTypeAsClauses.ts, 25, 75)) + +type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & string}2` +>TD3 : Symbol(TD3, Decl(mappedTypeAsClauses.ts, 27, 21)) +>U : Symbol(U, Decl(mappedTypeAsClauses.ts, 28, 9)) +>DoubleProp : Symbol(DoubleProp, Decl(mappedTypeAsClauses.ts, 21, 85)) +>U : Symbol(U, Decl(mappedTypeAsClauses.ts, 28, 9)) + diff --git a/tests/baselines/reference/mappedTypeAsClauses.types b/tests/baselines/reference/mappedTypeAsClauses.types new file mode 100644 index 0000000000000..438d9c1fcbf6f --- /dev/null +++ b/tests/baselines/reference/mappedTypeAsClauses.types @@ -0,0 +1,68 @@ +=== tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts === +// Mapped type 'as N' clauses + +type Getters = { [P in keyof T & string as `get${capitalize P}`]: () => T[P] }; +>Getters : Getters + +type TG1 = Getters<{ foo: string, bar: number, baz: { z: boolean } }>; +>TG1 : Getters<{ foo: string; bar: number; baz: { z: boolean;}; }> +>foo : string +>bar : number +>baz : { z: boolean; } +>z : boolean + +// Mapped type with 'as N' clause has no constraint on 'in T' clause + +type PropDef = { name: K, type: T }; +>PropDef : PropDef +>name : K +>type : T + +type TypeFromDefs> = { [P in T as P['name']]: P['type'] }; +>TypeFromDefs : TypeFromDefs + +type TP1 = TypeFromDefs<{ name: 'a', type: string } | { name: 'b', type: number } | { name: 'a', type: boolean }>; +>TP1 : TypeFromDefs<{ name: 'a'; type: string; } | { name: 'b'; type: number; } | { name: 'a'; type: boolean; }> +>name : "a" +>type : string +>name : "b" +>type : number +>name : "a" +>type : boolean + +// No array or tuple type mapping when 'as N' clause present + +type TA1 = Getters; +>TA1 : Getters + +type TA2 = Getters<[number, boolean]>; +>TA2 : Getters<[number, boolean]> + +// Filtering using 'as N' clause + +type Methods = { [P in keyof T as T[P] extends Function ? P : never]: T[P] }; +>Methods : Methods + +type TM1 = Methods<{ foo(): number, bar(x: string): boolean, baz: string | number }>; +>TM1 : Methods<{ foo(): number; bar(x: string): boolean; baz: string | number; }> +>foo : () => number +>bar : (x: string) => boolean +>x : string +>baz : string | number + +// Mapping to multiple names using 'as N' clause + +type DoubleProp = { [P in keyof T & string as `${P}1` | `${P}2`]: T[P] } +>DoubleProp : DoubleProp + +type TD1 = DoubleProp<{ a: string, b: number }>; // { a1: string, a2: string, b1: number, b2: number } +>TD1 : DoubleProp<{ a: string; b: number; }> +>a : string +>b : number + +type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2' +>TD2 : "a1" | "b1" | "a2" | "b2" + +type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & string}2` +>TD3 : `${keyof U & string}1` | `${keyof U & string}2` + diff --git a/tests/baselines/reference/mappedTypesArraysTuples.types b/tests/baselines/reference/mappedTypesArraysTuples.types index 2ec00ad565e3e..ba7d3dc50bdf4 100644 --- a/tests/baselines/reference/mappedTypesArraysTuples.types +++ b/tests/baselines/reference/mappedTypesArraysTuples.types @@ -66,7 +66,7 @@ type B = { b: string }; >b : string type T40 = Boxified | [A, B] | string | string[]>; ->T40 : string | Box[] | Boxified | readonly Box[] | Box[] | [Box, Box] +>T40 : string | Box[] | Boxified | readonly Box[] | [Box, Box] | Box[] type ReadWrite = { -readonly [P in keyof T] : T[P] }; >ReadWrite : ReadWrite diff --git a/tests/baselines/reference/objectLiteralExcessProperties.errors.txt b/tests/baselines/reference/objectLiteralExcessProperties.errors.txt index 29263c36d5442..9f193c8428d27 100644 --- a/tests/baselines/reference/objectLiteralExcessProperties.errors.txt +++ b/tests/baselines/reference/objectLiteralExcessProperties.errors.txt @@ -26,7 +26,7 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(41,11): error TS2322: Type '{ name: string; prop: boolean; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'any'. tests/cases/compiler/objectLiteralExcessProperties.ts(43,43): error TS2322: Type '{ name: string; prop: true; }' is not assignable to type 'T | { prop: boolean; }'. Object literal may only specify known properties, and 'name' does not exist in type '{ prop: boolean; }'. -tests/cases/compiler/objectLiteralExcessProperties.ts(45,76): error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type '{ name: string; } | (T & { prop: boolean; })'. +tests/cases/compiler/objectLiteralExcessProperties.ts(45,76): error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type '(T & { prop: boolean; }) | { name: string; }'. Object literal may only specify known properties, and 'prop' does not exist in type '{ name: string; }'. tests/cases/compiler/objectLiteralExcessProperties.ts(49,44): error TS2322: Type '{ z: string; }' is not assignable to type 'object & { x: string; }'. Object literal may only specify known properties, and 'z' does not exist in type 'object & { x: string; }'. @@ -122,7 +122,7 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(49,44): error TS2322: Type // Excess property checks only on non-generic parts of unions const obj4: T & { prop: boolean } | { name: string } = { name: "test", prop: true }; ~~~~~~~~~~ -!!! error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type '{ name: string; } | (T & { prop: boolean; })'. +!!! error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type '(T & { prop: boolean; }) | { name: string; }'. !!! error TS2322: Object literal may only specify known properties, and 'prop' does not exist in type '{ name: string; }'. // No excess property checks when union includes 'object' type const obj5: object | { x: string } = { z: 'abc' } diff --git a/tests/baselines/reference/objectLiteralExcessProperties.types b/tests/baselines/reference/objectLiteralExcessProperties.types index 812f48c89048c..535bf554fffae 100644 --- a/tests/baselines/reference/objectLiteralExcessProperties.types +++ b/tests/baselines/reference/objectLiteralExcessProperties.types @@ -132,7 +132,7 @@ function test() { // Excess property checks only on non-generic parts of unions const obj4: T & { prop: boolean } | { name: string } = { name: "test", prop: true }; ->obj4 : { name: string; } | (T & { prop: boolean; }) +>obj4 : (T & { prop: boolean; }) | { name: string; } >prop : boolean >name : string >{ name: "test", prop: true } : { name: string; prop: boolean; } diff --git a/tests/baselines/reference/privatePropertyInUnion.types b/tests/baselines/reference/privatePropertyInUnion.types index 1bc4ea394773a..8a618b09e063a 100644 --- a/tests/baselines/reference/privatePropertyInUnion.types +++ b/tests/baselines/reference/privatePropertyInUnion.types @@ -2,7 +2,7 @@ // Repro from #38236 type Type = string | object; ->Type : string | object +>Type : Type class SyncableObject { >SyncableObject : SyncableObject diff --git a/tests/baselines/reference/stringLiteralTypesInUnionTypes01.types b/tests/baselines/reference/stringLiteralTypesInUnionTypes01.types index fc6e0921a8ac6..3f0ff14b4eeb9 100644 --- a/tests/baselines/reference/stringLiteralTypesInUnionTypes01.types +++ b/tests/baselines/reference/stringLiteralTypesInUnionTypes01.types @@ -1,18 +1,18 @@ === tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes01.ts === type T = "foo" | "bar" | "baz"; ->T : "foo" | "bar" | "baz" +>T : T var x: "foo" | "bar" | "baz" = undefined; ->x : "foo" | "bar" | "baz" +>x : T >undefined : undefined var y: T = undefined; ->y : "foo" | "bar" | "baz" +>y : T >undefined : undefined if (x === "foo") { >x === "foo" : boolean ->x : "foo" | "bar" | "baz" +>x : T >"foo" : "foo" let a = x; @@ -25,10 +25,10 @@ else if (x !== "bar") { >"bar" : "bar" let b = x || y; ->b : "foo" | "bar" | "baz" ->x || y : "foo" | "bar" | "baz" +>b : T +>x || y : T >x : "baz" ->y : "foo" | "bar" | "baz" +>y : T } else { let c = x; @@ -36,25 +36,25 @@ else { >x : "bar" let d = y; ->d : "foo" | "bar" | "baz" ->y : "foo" | "bar" | "baz" +>d : T +>y : T let e: (typeof x) | (typeof y) = c || d; ->e : "foo" | "bar" | "baz" +>e : T >x : "bar" ->y : "foo" | "bar" | "baz" ->c || d : "foo" | "bar" | "baz" +>y : T +>c || d : T >c : "bar" ->d : "foo" | "bar" | "baz" +>d : T } x = y; ->x = y : "foo" | "bar" | "baz" ->x : "foo" | "bar" | "baz" ->y : "foo" | "bar" | "baz" +>x = y : T +>x : T +>y : T y = x; ->y = x : "foo" | "bar" | "baz" ->y : "foo" | "bar" | "baz" ->x : "foo" | "bar" | "baz" +>y = x : T +>y : T +>x : T diff --git a/tests/baselines/reference/stringLiteralTypesInUnionTypes03.types b/tests/baselines/reference/stringLiteralTypesInUnionTypes03.types index a4c8ec05d28c4..0dc76b30ad036 100644 --- a/tests/baselines/reference/stringLiteralTypesInUnionTypes03.types +++ b/tests/baselines/reference/stringLiteralTypesInUnionTypes03.types @@ -1,17 +1,17 @@ === tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes03.ts === type T = number | "foo" | "bar"; ->T : number | "foo" | "bar" +>T : T var x: "foo" | "bar" | number; ->x : number | "foo" | "bar" +>x : T var y: T = undefined; ->y : number | "foo" | "bar" +>y : T >undefined : undefined if (x === "foo") { >x === "foo" : boolean ->x : number | "foo" | "bar" +>x : T >"foo" : "foo" let a = x; @@ -24,10 +24,10 @@ else if (x !== "bar") { >"bar" : "bar" let b = x || y; ->b : number | "foo" | "bar" ->x || y : number | "foo" | "bar" +>b : T +>x || y : T >x : number ->y : number | "foo" | "bar" +>y : T } else { let c = x; @@ -35,25 +35,25 @@ else { >x : "bar" let d = y; ->d : number | "foo" | "bar" ->y : number | "foo" | "bar" +>d : T +>y : T let e: (typeof x) | (typeof y) = c || d; ->e : number | "foo" | "bar" +>e : T >x : "bar" ->y : number | "foo" | "bar" ->c || d : number | "foo" | "bar" +>y : T +>c || d : T >c : "bar" ->d : number | "foo" | "bar" +>d : T } x = y; ->x = y : number | "foo" | "bar" ->x : number | "foo" | "bar" ->y : number | "foo" | "bar" +>x = y : T +>x : T +>y : T y = x; ->y = x : number | "foo" | "bar" ->y : number | "foo" | "bar" ->x : number | "foo" | "bar" +>y = x : T +>y : T +>x : T diff --git a/tests/baselines/reference/templateLiteralTypes1.errors.txt b/tests/baselines/reference/templateLiteralTypes1.errors.txt new file mode 100644 index 0000000000000..055bb929a98bd --- /dev/null +++ b/tests/baselines/reference/templateLiteralTypes1.errors.txt @@ -0,0 +1,219 @@ +tests/cases/conformance/types/literal/templateLiteralTypes1.ts(34,5): error TS2322: Type 'T' is not assignable to type '{ [P in keyof T & string as `p_${P}`]: T[P]; }'. +tests/cases/conformance/types/literal/templateLiteralTypes1.ts(39,5): error TS2322: Type '{ [P in B as `p_${P}`]: T; }' is not assignable to type '{ [Q in A as `p_${Q}`]: U; }'. + Type 'A' is not assignable to type 'B'. + 'A' is assignable to the constraint of type 'B', but 'B' could be instantiated with a different subtype of constraint 'string'. + Type 'string' is not assignable to type 'B'. + 'string' is assignable to the constraint of type 'B', but 'B' could be instantiated with a different subtype of constraint 'string'. +tests/cases/conformance/types/literal/templateLiteralTypes1.ts(184,16): error TS2590: Expression produces a union type that is too complex to represent. +tests/cases/conformance/types/literal/templateLiteralTypes1.ts(188,16): error TS2590: Expression produces a union type that is too complex to represent. +tests/cases/conformance/types/literal/templateLiteralTypes1.ts(192,16): error TS2590: Expression produces a union type that is too complex to represent. + + +==== tests/cases/conformance/types/literal/templateLiteralTypes1.ts (5 errors) ==== + // Template types example from #12754 + + const createScopedActionType = (scope: S) => (type: T) => `${scope}/${type}` as `${S}/${T}`; + const createActionInMyScope = createScopedActionType("MyScope"); // (type: T) => `MyScope/${T}` + const MY_ACTION = createActionInMyScope("MY_ACTION"); // 'MyScope/MY_ACTION' + + // Union types are distributed over template types + + type EventName = `${S}Changed`; + type EN1 = EventName<'Foo' | 'Bar' | 'Baz'>; + type Loc = `${'top' | 'middle' | 'bottom'}-${'left' | 'center' | 'right'}`; + + // Primitive literal types can be spread into templates + + type ToString = `${T}`; + type TS1 = ToString<'abc' | 42 | true | -1234n>; + + // Casing modifiers + + type Cases = `${uppercase T} ${lowercase T} ${capitalize T} ${uncapitalize T}`; + + type TCA1 = Cases<'bar'>; // 'BAR bar Bar bar' + type TCA2 = Cases<'BAR'>; // 'BAR bar BAR bAR' + + // Assignability + + function test(name: `get${capitalize T}`) { + let s1: string = name; + let s2: 'getFoo' | 'getBar' = name; + } + + function fa1(x: T, y: { [P in keyof T]: T[P] }, z: { [P in keyof T & string as `p_${P}`]: T[P] }) { + y = x; + z = x; // Error + ~ +!!! error TS2322: Type 'T' is not assignable to type '{ [P in keyof T & string as `p_${P}`]: T[P]; }'. + } + + function fa2(x: { [P in B as `p_${P}`]: T }, y: { [Q in A as `p_${Q}`]: U }) { + x = y; + y = x; // Error + ~ +!!! error TS2322: Type '{ [P in B as `p_${P}`]: T; }' is not assignable to type '{ [Q in A as `p_${Q}`]: U; }'. +!!! error TS2322: Type 'A' is not assignable to type 'B'. +!!! error TS2322: 'A' is assignable to the constraint of type 'B', but 'B' could be instantiated with a different subtype of constraint 'string'. +!!! error TS2322: Type 'string' is not assignable to type 'B'. +!!! error TS2322: 'string' is assignable to the constraint of type 'B', but 'B' could be instantiated with a different subtype of constraint 'string'. + } + + // String transformations using recursive conditional types + + type Join = + T extends [] ? '' : + T extends [unknown] ? `${T[0]}` : + T extends [unknown, ...infer U] ? `${T[0]}${D}${Join}` : + string; + + type TJ1 = Join<[1, 2, 3, 4], '.'> + type TJ2 = Join<['foo', 'bar', 'baz'], '-'>; + type TJ3 = Join<[], '.'> + + // Inference based on delimiters + + type MatchPair = S extends `[${infer A},${infer B}]` ? [A, B] : unknown; + + type T20 = MatchPair<'[1,2]'>; // ['1', '2'] + type T21 = MatchPair<'[foo,bar]'>; // ['foo', 'bar'] + type T22 = MatchPair<' [1,2]'>; // unknown + type T23 = MatchPair<'[123]'>; // unknown + type T24 = MatchPair<'[1,2,3,4]'>; // ['1', '2,3,4'] + + type SnakeToCamelCase = + S extends `${infer T}_${infer U}` ? `${lowercase T}${SnakeToPascalCase}` : + S extends `${infer T}` ? `${lowercase T}` : + SnakeToPascalCase; + + type SnakeToPascalCase = + string extends S ? string : + S extends `${infer T}_${infer U}` ? `${capitalize `${lowercase T}`}${SnakeToPascalCase}` : + S extends `${infer T}` ? `${capitalize `${lowercase T}`}` : + never; + + type RR0 = SnakeToPascalCase<'hello_world_foo'>; // 'HelloWorldFoo' + type RR1 = SnakeToPascalCase<'FOO_BAR_BAZ'>; // 'FooBarBaz' + type RR2 = SnakeToCamelCase<'hello_world_foo'>; // 'helloWorldFoo' + type RR3 = SnakeToCamelCase<'FOO_BAR_BAZ'>; // 'fooBarBaz' + + // Single character inference + + type FirstTwoAndRest = S extends `${infer A}${infer B}${infer R}` ? [`${A}${B}`, R] : unknown; + + type T25 = FirstTwoAndRest<'abcde'>; // ['ab', 'cde'] + type T26 = FirstTwoAndRest<'ab'>; // ['ab', ''] + type T27 = FirstTwoAndRest<'a'>; // unknown + + type Capitalize = S extends `${infer H}${infer T}` ? `${uppercase H}${T}` : S; + type Uncapitalize = S extends `${infer H}${infer T}` ? `${lowercase H}${T}` : S; + + type TC1 = Capitalize<'foo'>; // 'Foo' + type TC2 = Uncapitalize<'Foo'>; // 'foo' + + type HexDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' |'8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'; + + type HexColor = + S extends `#${infer R1}${infer R2}${infer G1}${infer G2}${infer B1}${infer B2}` ? + [R1, R2, G1, G2, B1, B2] extends [HexDigit, HexDigit, HexDigit, HexDigit, HexDigit, HexDigit] ? + S : + never : + never; + + type TH1 = HexColor<'#8080FF'>; // '#8080FF' + type TH2 = HexColor<'#80c0ff'>; // '#80c0ff' + type TH3 = HexColor<'#8080F'>; // never + type TH4 = HexColor<'#8080FFF'>; // never + + // Recursive inference + + type Trim = + S extends ` ${infer T}` ? Trim : + S extends `${infer T} ` ? Trim : + S; + + type TR1 = Trim<'xx '>; // 'xx' + type TR2 = Trim<' xx'>; // 'xx' + type TR3 = Trim<' xx '>; // 'xx' + + type Split = + string extends S ? string[] : + S extends '' ? [] : + S extends `${infer T}${D}${infer U}` ? [T, ...Split] : + [S]; + + type T40 = Split<'foo', '.'>; // ['foo'] + type T41 = Split<'foo.bar.baz', '.'>; // ['foo', 'bar', 'baz'] + type T42 = Split<'foo.bar', ''>; // ['f', 'o', 'o', '.', 'b', 'a', 'r'] + type T43 = Split; // string[] + + // Inference and property name paths + + declare function getProp(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; + declare function getProp(obj: T, path: `${P0}.${P1}`): T[P0][P1]; + declare function getProp(obj: T, path: P0): T[P0]; + declare function getProp(obj: object, path: string): unknown; + + let p1 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a'); + let p2 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a.b'); + let p3 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a.b.d'); + + type PropType = + string extends Path ? unknown : + Path extends keyof T ? T[Path] : + Path extends `${infer K}.${infer R}` ? K extends keyof T ? PropType : unknown : + unknown; + + declare function getPropValue(obj: T, path: P): PropType; + declare const s: string; + + const obj = { a: { b: {c: 42, d: 'hello' }}}; + + getPropValue(obj, 'a'); // { b: {c: number, d: string } } + getPropValue(obj, 'a.b'); // {c: number, d: string } + getPropValue(obj, 'a.b.d'); // string + getPropValue(obj, 'a.b.x'); // unknown + getPropValue(obj, s); // unknown + + // Infer type variables in template literals have string constraint + + type S1 = T extends `foo${infer U}bar` ? S2 : never; + type S2 = S; + + // Batched single character inferences for lower recursion depth + + type Chars = + string extends S ? string[] : + S extends `${infer C0}${infer C1}${infer C2}${infer C3}${infer C4}${infer C5}${infer C6}${infer C7}${infer C8}${infer C9}${infer R}` ? [C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, ...Chars] : + S extends `${infer C}${infer R}` ? [C, ...Chars] : + S extends '' ? [] : + never; + + type L1 = Chars<'FooBarBazThisIsALongerString'>; // ['F', 'o', 'o', 'B', 'a', 'r', ...] + + // Cross product unions limited to 100,000 constituents + + type A = any; + + type U1 = {a1:A} | {b1:A} | {c1:A} | {d1:A} | {e1:A} | {f1:A} | {g1:A} | {h1:A} | {i1:A} | {j1:A}; + type U2 = {a2:A} | {b2:A} | {c2:A} | {d2:A} | {e2:A} | {f2:A} | {g2:A} | {h2:A} | {i2:A} | {j2:A}; + type U3 = {a3:A} | {b3:A} | {c3:A} | {d3:A} | {e3:A} | {f3:A} | {g3:A} | {h3:A} | {i3:A} | {j3:A}; + type U4 = {a4:A} | {b4:A} | {c4:A} | {d4:A} | {e4:A} | {f4:A} | {g4:A} | {h4:A} | {i4:A} | {j4:A}; + type U5 = {a5:A} | {b5:A} | {c5:A} | {d5:A} | {e5:A} | {f5:A} | {g5:A} | {h5:A} | {i5:A} | {j5:A}; + + type U100000 = U1 & U2 & U3 & U4 & U5; // Error + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2590: Expression produces a union type that is too complex to represent. + + type Digits = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + + type D100000 = `${Digits}${Digits}${Digits}${Digits}${Digits}`; // Error + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2590: Expression produces a union type that is too complex to represent. + + type TDigits = [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9]; + + type T100000 = [...TDigits, ...TDigits, ...TDigits, ...TDigits, ...TDigits]; // Error + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2590: Expression produces a union type that is too complex to represent. + \ No newline at end of file diff --git a/tests/baselines/reference/templateLiteralTypes1.js b/tests/baselines/reference/templateLiteralTypes1.js new file mode 100644 index 0000000000000..c056b9bc1e7a1 --- /dev/null +++ b/tests/baselines/reference/templateLiteralTypes1.js @@ -0,0 +1,437 @@ +//// [templateLiteralTypes1.ts] +// Template types example from #12754 + +const createScopedActionType = (scope: S) => (type: T) => `${scope}/${type}` as `${S}/${T}`; +const createActionInMyScope = createScopedActionType("MyScope"); // (type: T) => `MyScope/${T}` +const MY_ACTION = createActionInMyScope("MY_ACTION"); // 'MyScope/MY_ACTION' + +// Union types are distributed over template types + +type EventName = `${S}Changed`; +type EN1 = EventName<'Foo' | 'Bar' | 'Baz'>; +type Loc = `${'top' | 'middle' | 'bottom'}-${'left' | 'center' | 'right'}`; + +// Primitive literal types can be spread into templates + +type ToString = `${T}`; +type TS1 = ToString<'abc' | 42 | true | -1234n>; + +// Casing modifiers + +type Cases = `${uppercase T} ${lowercase T} ${capitalize T} ${uncapitalize T}`; + +type TCA1 = Cases<'bar'>; // 'BAR bar Bar bar' +type TCA2 = Cases<'BAR'>; // 'BAR bar BAR bAR' + +// Assignability + +function test(name: `get${capitalize T}`) { + let s1: string = name; + let s2: 'getFoo' | 'getBar' = name; +} + +function fa1(x: T, y: { [P in keyof T]: T[P] }, z: { [P in keyof T & string as `p_${P}`]: T[P] }) { + y = x; + z = x; // Error +} + +function fa2(x: { [P in B as `p_${P}`]: T }, y: { [Q in A as `p_${Q}`]: U }) { + x = y; + y = x; // Error +} + +// String transformations using recursive conditional types + +type Join = + T extends [] ? '' : + T extends [unknown] ? `${T[0]}` : + T extends [unknown, ...infer U] ? `${T[0]}${D}${Join}` : + string; + +type TJ1 = Join<[1, 2, 3, 4], '.'> +type TJ2 = Join<['foo', 'bar', 'baz'], '-'>; +type TJ3 = Join<[], '.'> + +// Inference based on delimiters + +type MatchPair = S extends `[${infer A},${infer B}]` ? [A, B] : unknown; + +type T20 = MatchPair<'[1,2]'>; // ['1', '2'] +type T21 = MatchPair<'[foo,bar]'>; // ['foo', 'bar'] +type T22 = MatchPair<' [1,2]'>; // unknown +type T23 = MatchPair<'[123]'>; // unknown +type T24 = MatchPair<'[1,2,3,4]'>; // ['1', '2,3,4'] + +type SnakeToCamelCase = + S extends `${infer T}_${infer U}` ? `${lowercase T}${SnakeToPascalCase}` : + S extends `${infer T}` ? `${lowercase T}` : + SnakeToPascalCase; + +type SnakeToPascalCase = + string extends S ? string : + S extends `${infer T}_${infer U}` ? `${capitalize `${lowercase T}`}${SnakeToPascalCase}` : + S extends `${infer T}` ? `${capitalize `${lowercase T}`}` : + never; + +type RR0 = SnakeToPascalCase<'hello_world_foo'>; // 'HelloWorldFoo' +type RR1 = SnakeToPascalCase<'FOO_BAR_BAZ'>; // 'FooBarBaz' +type RR2 = SnakeToCamelCase<'hello_world_foo'>; // 'helloWorldFoo' +type RR3 = SnakeToCamelCase<'FOO_BAR_BAZ'>; // 'fooBarBaz' + +// Single character inference + +type FirstTwoAndRest = S extends `${infer A}${infer B}${infer R}` ? [`${A}${B}`, R] : unknown; + +type T25 = FirstTwoAndRest<'abcde'>; // ['ab', 'cde'] +type T26 = FirstTwoAndRest<'ab'>; // ['ab', ''] +type T27 = FirstTwoAndRest<'a'>; // unknown + +type Capitalize = S extends `${infer H}${infer T}` ? `${uppercase H}${T}` : S; +type Uncapitalize = S extends `${infer H}${infer T}` ? `${lowercase H}${T}` : S; + +type TC1 = Capitalize<'foo'>; // 'Foo' +type TC2 = Uncapitalize<'Foo'>; // 'foo' + +type HexDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' |'8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'; + +type HexColor = + S extends `#${infer R1}${infer R2}${infer G1}${infer G2}${infer B1}${infer B2}` ? + [R1, R2, G1, G2, B1, B2] extends [HexDigit, HexDigit, HexDigit, HexDigit, HexDigit, HexDigit] ? + S : + never : + never; + +type TH1 = HexColor<'#8080FF'>; // '#8080FF' +type TH2 = HexColor<'#80c0ff'>; // '#80c0ff' +type TH3 = HexColor<'#8080F'>; // never +type TH4 = HexColor<'#8080FFF'>; // never + +// Recursive inference + +type Trim = + S extends ` ${infer T}` ? Trim : + S extends `${infer T} ` ? Trim : + S; + +type TR1 = Trim<'xx '>; // 'xx' +type TR2 = Trim<' xx'>; // 'xx' +type TR3 = Trim<' xx '>; // 'xx' + +type Split = + string extends S ? string[] : + S extends '' ? [] : + S extends `${infer T}${D}${infer U}` ? [T, ...Split] : + [S]; + +type T40 = Split<'foo', '.'>; // ['foo'] +type T41 = Split<'foo.bar.baz', '.'>; // ['foo', 'bar', 'baz'] +type T42 = Split<'foo.bar', ''>; // ['f', 'o', 'o', '.', 'b', 'a', 'r'] +type T43 = Split; // string[] + +// Inference and property name paths + +declare function getProp(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; +declare function getProp(obj: T, path: `${P0}.${P1}`): T[P0][P1]; +declare function getProp(obj: T, path: P0): T[P0]; +declare function getProp(obj: object, path: string): unknown; + +let p1 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a'); +let p2 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a.b'); +let p3 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a.b.d'); + +type PropType = + string extends Path ? unknown : + Path extends keyof T ? T[Path] : + Path extends `${infer K}.${infer R}` ? K extends keyof T ? PropType : unknown : + unknown; + +declare function getPropValue(obj: T, path: P): PropType; +declare const s: string; + +const obj = { a: { b: {c: 42, d: 'hello' }}}; + +getPropValue(obj, 'a'); // { b: {c: number, d: string } } +getPropValue(obj, 'a.b'); // {c: number, d: string } +getPropValue(obj, 'a.b.d'); // string +getPropValue(obj, 'a.b.x'); // unknown +getPropValue(obj, s); // unknown + +// Infer type variables in template literals have string constraint + +type S1 = T extends `foo${infer U}bar` ? S2 : never; +type S2 = S; + +// Batched single character inferences for lower recursion depth + +type Chars = + string extends S ? string[] : + S extends `${infer C0}${infer C1}${infer C2}${infer C3}${infer C4}${infer C5}${infer C6}${infer C7}${infer C8}${infer C9}${infer R}` ? [C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, ...Chars] : + S extends `${infer C}${infer R}` ? [C, ...Chars] : + S extends '' ? [] : + never; + +type L1 = Chars<'FooBarBazThisIsALongerString'>; // ['F', 'o', 'o', 'B', 'a', 'r', ...] + +// Cross product unions limited to 100,000 constituents + +type A = any; + +type U1 = {a1:A} | {b1:A} | {c1:A} | {d1:A} | {e1:A} | {f1:A} | {g1:A} | {h1:A} | {i1:A} | {j1:A}; +type U2 = {a2:A} | {b2:A} | {c2:A} | {d2:A} | {e2:A} | {f2:A} | {g2:A} | {h2:A} | {i2:A} | {j2:A}; +type U3 = {a3:A} | {b3:A} | {c3:A} | {d3:A} | {e3:A} | {f3:A} | {g3:A} | {h3:A} | {i3:A} | {j3:A}; +type U4 = {a4:A} | {b4:A} | {c4:A} | {d4:A} | {e4:A} | {f4:A} | {g4:A} | {h4:A} | {i4:A} | {j4:A}; +type U5 = {a5:A} | {b5:A} | {c5:A} | {d5:A} | {e5:A} | {f5:A} | {g5:A} | {h5:A} | {i5:A} | {j5:A}; + +type U100000 = U1 & U2 & U3 & U4 & U5; // Error + +type Digits = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + +type D100000 = `${Digits}${Digits}${Digits}${Digits}${Digits}`; // Error + +type TDigits = [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9]; + +type T100000 = [...TDigits, ...TDigits, ...TDigits, ...TDigits, ...TDigits]; // Error + + +//// [templateLiteralTypes1.js] +"use strict"; +// Template types example from #12754 +var createScopedActionType = function (scope) { return function (type) { return scope + "/" + type; }; }; +var createActionInMyScope = createScopedActionType("MyScope"); // (type: T) => `MyScope/${T}` +var MY_ACTION = createActionInMyScope("MY_ACTION"); // 'MyScope/MY_ACTION' +// Assignability +function test(name) { + var s1 = name; + var s2 = name; +} +function fa1(x, y, z) { + y = x; + z = x; // Error +} +function fa2(x, y) { + x = y; + y = x; // Error +} +var p1 = getProp({ a: { b: { c: 42, d: 'hello' } } }, 'a'); +var p2 = getProp({ a: { b: { c: 42, d: 'hello' } } }, 'a.b'); +var p3 = getProp({ a: { b: { c: 42, d: 'hello' } } }, 'a.b.d'); +var obj = { a: { b: { c: 42, d: 'hello' } } }; +getPropValue(obj, 'a'); // { b: {c: number, d: string } } +getPropValue(obj, 'a.b'); // {c: number, d: string } +getPropValue(obj, 'a.b.d'); // string +getPropValue(obj, 'a.b.x'); // unknown +getPropValue(obj, s); // unknown + + +//// [templateLiteralTypes1.d.ts] +declare const createScopedActionType: (scope: S) => (type: T) => `${S}/${T}`; +declare const createActionInMyScope: (type: T) => `MyScope/${T}`; +declare const MY_ACTION: "MyScope/MY_ACTION"; +declare type EventName = `${S}Changed`; +declare type EN1 = EventName<'Foo' | 'Bar' | 'Baz'>; +declare type Loc = `${'top' | 'middle' | 'bottom'}-${'left' | 'center' | 'right'}`; +declare type ToString = `${T}`; +declare type TS1 = ToString<'abc' | 42 | true | -1234n>; +declare type Cases = `${uppercase T} ${lowercase T} ${capitalize T} ${uncapitalize T}`; +declare type TCA1 = Cases<'bar'>; +declare type TCA2 = Cases<'BAR'>; +declare function test(name: `get${capitalize T}`): void; +declare function fa1(x: T, y: { + [P in keyof T]: T[P]; +}, z: { + [P in keyof T & string as `p_${P}`]: T[P]; +}): void; +declare function fa2(x: { + [P in B as `p_${P}`]: T; +}, y: { + [Q in A as `p_${Q}`]: U; +}): void; +declare type Join = T extends [] ? '' : T extends [unknown] ? `${T[0]}` : T extends [unknown, ...infer U] ? `${T[0]}${D}${Join}` : string; +declare type TJ1 = Join<[1, 2, 3, 4], '.'>; +declare type TJ2 = Join<['foo', 'bar', 'baz'], '-'>; +declare type TJ3 = Join<[], '.'>; +declare type MatchPair = S extends `[${infer A},${infer B}]` ? [A, B] : unknown; +declare type T20 = MatchPair<'[1,2]'>; +declare type T21 = MatchPair<'[foo,bar]'>; +declare type T22 = MatchPair<' [1,2]'>; +declare type T23 = MatchPair<'[123]'>; +declare type T24 = MatchPair<'[1,2,3,4]'>; +declare type SnakeToCamelCase = S extends `${infer T}_${infer U}` ? `${lowercase T}${SnakeToPascalCase}` : S extends `${infer T}` ? `${lowercase T}` : SnakeToPascalCase; +declare type SnakeToPascalCase = string extends S ? string : S extends `${infer T}_${infer U}` ? `${capitalize `${lowercase T}`}${SnakeToPascalCase}` : S extends `${infer T}` ? `${capitalize `${lowercase T}`}` : never; +declare type RR0 = SnakeToPascalCase<'hello_world_foo'>; +declare type RR1 = SnakeToPascalCase<'FOO_BAR_BAZ'>; +declare type RR2 = SnakeToCamelCase<'hello_world_foo'>; +declare type RR3 = SnakeToCamelCase<'FOO_BAR_BAZ'>; +declare type FirstTwoAndRest = S extends `${infer A}${infer B}${infer R}` ? [`${A}${B}`, R] : unknown; +declare type T25 = FirstTwoAndRest<'abcde'>; +declare type T26 = FirstTwoAndRest<'ab'>; +declare type T27 = FirstTwoAndRest<'a'>; +declare type Capitalize = S extends `${infer H}${infer T}` ? `${uppercase H}${T}` : S; +declare type Uncapitalize = S extends `${infer H}${infer T}` ? `${lowercase H}${T}` : S; +declare type TC1 = Capitalize<'foo'>; +declare type TC2 = Uncapitalize<'Foo'>; +declare type HexDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'; +declare type HexColor = S extends `#${infer R1}${infer R2}${infer G1}${infer G2}${infer B1}${infer B2}` ? [ + R1, + R2, + G1, + G2, + B1, + B2 +] extends [HexDigit, HexDigit, HexDigit, HexDigit, HexDigit, HexDigit] ? S : never : never; +declare type TH1 = HexColor<'#8080FF'>; +declare type TH2 = HexColor<'#80c0ff'>; +declare type TH3 = HexColor<'#8080F'>; +declare type TH4 = HexColor<'#8080FFF'>; +declare type Trim = S extends ` ${infer T}` ? Trim : S extends `${infer T} ` ? Trim : S; +declare type TR1 = Trim<'xx '>; +declare type TR2 = Trim<' xx'>; +declare type TR3 = Trim<' xx '>; +declare type Split = string extends S ? string[] : S extends '' ? [] : S extends `${infer T}${D}${infer U}` ? [T, ...Split] : [ + S +]; +declare type T40 = Split<'foo', '.'>; +declare type T41 = Split<'foo.bar.baz', '.'>; +declare type T42 = Split<'foo.bar', ''>; +declare type T43 = Split; +declare function getProp(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; +declare function getProp(obj: T, path: `${P0}.${P1}`): T[P0][P1]; +declare function getProp(obj: T, path: P0): T[P0]; +declare function getProp(obj: object, path: string): unknown; +declare let p1: { + readonly b: { + readonly c: 42; + readonly d: "hello"; + }; +}; +declare let p2: { + readonly c: 42; + readonly d: "hello"; +}; +declare let p3: "hello"; +declare type PropType = string extends Path ? unknown : Path extends keyof T ? T[Path] : Path extends `${infer K}.${infer R}` ? K extends keyof T ? PropType : unknown : unknown; +declare function getPropValue(obj: T, path: P): PropType; +declare const s: string; +declare const obj: { + a: { + b: { + c: number; + d: string; + }; + }; +}; +declare type S1 = T extends `foo${infer U}bar` ? S2 : never; +declare type S2 = S; +declare type Chars = string extends S ? string[] : S extends `${infer C0}${infer C1}${infer C2}${infer C3}${infer C4}${infer C5}${infer C6}${infer C7}${infer C8}${infer C9}${infer R}` ? [C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, ...Chars] : S extends `${infer C}${infer R}` ? [C, ...Chars] : S extends '' ? [] : never; +declare type L1 = Chars<'FooBarBazThisIsALongerString'>; +declare type A = any; +declare type U1 = { + a1: A; +} | { + b1: A; +} | { + c1: A; +} | { + d1: A; +} | { + e1: A; +} | { + f1: A; +} | { + g1: A; +} | { + h1: A; +} | { + i1: A; +} | { + j1: A; +}; +declare type U2 = { + a2: A; +} | { + b2: A; +} | { + c2: A; +} | { + d2: A; +} | { + e2: A; +} | { + f2: A; +} | { + g2: A; +} | { + h2: A; +} | { + i2: A; +} | { + j2: A; +}; +declare type U3 = { + a3: A; +} | { + b3: A; +} | { + c3: A; +} | { + d3: A; +} | { + e3: A; +} | { + f3: A; +} | { + g3: A; +} | { + h3: A; +} | { + i3: A; +} | { + j3: A; +}; +declare type U4 = { + a4: A; +} | { + b4: A; +} | { + c4: A; +} | { + d4: A; +} | { + e4: A; +} | { + f4: A; +} | { + g4: A; +} | { + h4: A; +} | { + i4: A; +} | { + j4: A; +}; +declare type U5 = { + a5: A; +} | { + b5: A; +} | { + c5: A; +} | { + d5: A; +} | { + e5: A; +} | { + f5: A; +} | { + g5: A; +} | { + h5: A; +} | { + i5: A; +} | { + j5: A; +}; +declare type U100000 = U1 & U2 & U3 & U4 & U5; +declare type Digits = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; +declare type D100000 = `${Digits}${Digits}${Digits}${Digits}${Digits}`; +declare type TDigits = [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9]; +declare type T100000 = [...TDigits, ...TDigits, ...TDigits, ...TDigits, ...TDigits]; diff --git a/tests/baselines/reference/templateLiteralTypes1.symbols b/tests/baselines/reference/templateLiteralTypes1.symbols new file mode 100644 index 0000000000000..ce4fd7e0d3496 --- /dev/null +++ b/tests/baselines/reference/templateLiteralTypes1.symbols @@ -0,0 +1,813 @@ +=== tests/cases/conformance/types/literal/templateLiteralTypes1.ts === +// Template types example from #12754 + +const createScopedActionType = (scope: S) => (type: T) => `${scope}/${type}` as `${S}/${T}`; +>createScopedActionType : Symbol(createScopedActionType, Decl(templateLiteralTypes1.ts, 2, 5)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 2, 32)) +>scope : Symbol(scope, Decl(templateLiteralTypes1.ts, 2, 50)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 2, 32)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 2, 64)) +>type : Symbol(type, Decl(templateLiteralTypes1.ts, 2, 82)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 2, 64)) +>scope : Symbol(scope, Decl(templateLiteralTypes1.ts, 2, 50)) +>type : Symbol(type, Decl(templateLiteralTypes1.ts, 2, 82)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 2, 32)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 2, 64)) + +const createActionInMyScope = createScopedActionType("MyScope"); // (type: T) => `MyScope/${T}` +>createActionInMyScope : Symbol(createActionInMyScope, Decl(templateLiteralTypes1.ts, 3, 5)) +>createScopedActionType : Symbol(createScopedActionType, Decl(templateLiteralTypes1.ts, 2, 5)) + +const MY_ACTION = createActionInMyScope("MY_ACTION"); // 'MyScope/MY_ACTION' +>MY_ACTION : Symbol(MY_ACTION, Decl(templateLiteralTypes1.ts, 4, 5)) +>createActionInMyScope : Symbol(createActionInMyScope, Decl(templateLiteralTypes1.ts, 3, 5)) + +// Union types are distributed over template types + +type EventName = `${S}Changed`; +>EventName : Symbol(EventName, Decl(templateLiteralTypes1.ts, 4, 53)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 8, 15)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 8, 15)) + +type EN1 = EventName<'Foo' | 'Bar' | 'Baz'>; +>EN1 : Symbol(EN1, Decl(templateLiteralTypes1.ts, 8, 49)) +>EventName : Symbol(EventName, Decl(templateLiteralTypes1.ts, 4, 53)) + +type Loc = `${'top' | 'middle' | 'bottom'}-${'left' | 'center' | 'right'}`; +>Loc : Symbol(Loc, Decl(templateLiteralTypes1.ts, 9, 44)) + +// Primitive literal types can be spread into templates + +type ToString = `${T}`; +>ToString : Symbol(ToString, Decl(templateLiteralTypes1.ts, 10, 75)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 14, 14)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 14, 14)) + +type TS1 = ToString<'abc' | 42 | true | -1234n>; +>TS1 : Symbol(TS1, Decl(templateLiteralTypes1.ts, 14, 69)) +>ToString : Symbol(ToString, Decl(templateLiteralTypes1.ts, 10, 75)) + +// Casing modifiers + +type Cases = `${uppercase T} ${lowercase T} ${capitalize T} ${uncapitalize T}`; +>Cases : Symbol(Cases, Decl(templateLiteralTypes1.ts, 15, 48)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 19, 11)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 19, 11)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 19, 11)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 19, 11)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 19, 11)) + +type TCA1 = Cases<'bar'>; // 'BAR bar Bar bar' +>TCA1 : Symbol(TCA1, Decl(templateLiteralTypes1.ts, 19, 97)) +>Cases : Symbol(Cases, Decl(templateLiteralTypes1.ts, 15, 48)) + +type TCA2 = Cases<'BAR'>; // 'BAR bar BAR bAR' +>TCA2 : Symbol(TCA2, Decl(templateLiteralTypes1.ts, 21, 25)) +>Cases : Symbol(Cases, Decl(templateLiteralTypes1.ts, 15, 48)) + +// Assignability + +function test(name: `get${capitalize T}`) { +>test : Symbol(test, Decl(templateLiteralTypes1.ts, 22, 25)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 26, 14)) +>name : Symbol(name, Decl(templateLiteralTypes1.ts, 26, 39)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 26, 14)) + + let s1: string = name; +>s1 : Symbol(s1, Decl(templateLiteralTypes1.ts, 27, 7)) +>name : Symbol(name, Decl(templateLiteralTypes1.ts, 26, 39)) + + let s2: 'getFoo' | 'getBar' = name; +>s2 : Symbol(s2, Decl(templateLiteralTypes1.ts, 28, 7)) +>name : Symbol(name, Decl(templateLiteralTypes1.ts, 26, 39)) +} + +function fa1(x: T, y: { [P in keyof T]: T[P] }, z: { [P in keyof T & string as `p_${P}`]: T[P] }) { +>fa1 : Symbol(fa1, Decl(templateLiteralTypes1.ts, 29, 1)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 31, 13)) +>x : Symbol(x, Decl(templateLiteralTypes1.ts, 31, 16)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 31, 13)) +>y : Symbol(y, Decl(templateLiteralTypes1.ts, 31, 21)) +>P : Symbol(P, Decl(templateLiteralTypes1.ts, 31, 28)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 31, 13)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 31, 13)) +>P : Symbol(P, Decl(templateLiteralTypes1.ts, 31, 28)) +>z : Symbol(z, Decl(templateLiteralTypes1.ts, 31, 50)) +>P : Symbol(P, Decl(templateLiteralTypes1.ts, 31, 57)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 31, 13)) +>P : Symbol(P, Decl(templateLiteralTypes1.ts, 31, 57)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 31, 13)) +>P : Symbol(P, Decl(templateLiteralTypes1.ts, 31, 57)) + + y = x; +>y : Symbol(y, Decl(templateLiteralTypes1.ts, 31, 21)) +>x : Symbol(x, Decl(templateLiteralTypes1.ts, 31, 16)) + + z = x; // Error +>z : Symbol(z, Decl(templateLiteralTypes1.ts, 31, 50)) +>x : Symbol(x, Decl(templateLiteralTypes1.ts, 31, 16)) +} + +function fa2(x: { [P in B as `p_${P}`]: T }, y: { [Q in A as `p_${Q}`]: U }) { +>fa2 : Symbol(fa2, Decl(templateLiteralTypes1.ts, 34, 1)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 36, 13)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 36, 15)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 36, 13)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 36, 28)) +>B : Symbol(B, Decl(templateLiteralTypes1.ts, 36, 46)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 36, 28)) +>x : Symbol(x, Decl(templateLiteralTypes1.ts, 36, 60)) +>P : Symbol(P, Decl(templateLiteralTypes1.ts, 36, 66)) +>B : Symbol(B, Decl(templateLiteralTypes1.ts, 36, 46)) +>P : Symbol(P, Decl(templateLiteralTypes1.ts, 36, 66)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 36, 13)) +>y : Symbol(y, Decl(templateLiteralTypes1.ts, 36, 91)) +>Q : Symbol(Q, Decl(templateLiteralTypes1.ts, 36, 98)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 36, 28)) +>Q : Symbol(Q, Decl(templateLiteralTypes1.ts, 36, 98)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 36, 15)) + + x = y; +>x : Symbol(x, Decl(templateLiteralTypes1.ts, 36, 60)) +>y : Symbol(y, Decl(templateLiteralTypes1.ts, 36, 91)) + + y = x; // Error +>y : Symbol(y, Decl(templateLiteralTypes1.ts, 36, 91)) +>x : Symbol(x, Decl(templateLiteralTypes1.ts, 36, 60)) +} + +// String transformations using recursive conditional types + +type Join = +>Join : Symbol(Join, Decl(templateLiteralTypes1.ts, 39, 1)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 43, 10)) +>D : Symbol(D, Decl(templateLiteralTypes1.ts, 43, 59)) + + T extends [] ? '' : +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 43, 10)) + + T extends [unknown] ? `${T[0]}` : +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 43, 10)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 43, 10)) + + T extends [unknown, ...infer U] ? `${T[0]}${D}${Join}` : +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 43, 10)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 46, 32)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 43, 10)) +>D : Symbol(D, Decl(templateLiteralTypes1.ts, 43, 59)) +>Join : Symbol(Join, Decl(templateLiteralTypes1.ts, 39, 1)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 46, 32)) +>D : Symbol(D, Decl(templateLiteralTypes1.ts, 43, 59)) + + string; + +type TJ1 = Join<[1, 2, 3, 4], '.'> +>TJ1 : Symbol(TJ1, Decl(templateLiteralTypes1.ts, 47, 11)) +>Join : Symbol(Join, Decl(templateLiteralTypes1.ts, 39, 1)) + +type TJ2 = Join<['foo', 'bar', 'baz'], '-'>; +>TJ2 : Symbol(TJ2, Decl(templateLiteralTypes1.ts, 49, 34)) +>Join : Symbol(Join, Decl(templateLiteralTypes1.ts, 39, 1)) + +type TJ3 = Join<[], '.'> +>TJ3 : Symbol(TJ3, Decl(templateLiteralTypes1.ts, 50, 44)) +>Join : Symbol(Join, Decl(templateLiteralTypes1.ts, 39, 1)) + +// Inference based on delimiters + +type MatchPair = S extends `[${infer A},${infer B}]` ? [A, B] : unknown; +>MatchPair : Symbol(MatchPair, Decl(templateLiteralTypes1.ts, 51, 24)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 55, 15)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 55, 15)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 55, 54)) +>B : Symbol(B, Decl(templateLiteralTypes1.ts, 55, 65)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 55, 54)) +>B : Symbol(B, Decl(templateLiteralTypes1.ts, 55, 65)) + +type T20 = MatchPair<'[1,2]'>; // ['1', '2'] +>T20 : Symbol(T20, Decl(templateLiteralTypes1.ts, 55, 90)) +>MatchPair : Symbol(MatchPair, Decl(templateLiteralTypes1.ts, 51, 24)) + +type T21 = MatchPair<'[foo,bar]'>; // ['foo', 'bar'] +>T21 : Symbol(T21, Decl(templateLiteralTypes1.ts, 57, 30)) +>MatchPair : Symbol(MatchPair, Decl(templateLiteralTypes1.ts, 51, 24)) + +type T22 = MatchPair<' [1,2]'>; // unknown +>T22 : Symbol(T22, Decl(templateLiteralTypes1.ts, 58, 34)) +>MatchPair : Symbol(MatchPair, Decl(templateLiteralTypes1.ts, 51, 24)) + +type T23 = MatchPair<'[123]'>; // unknown +>T23 : Symbol(T23, Decl(templateLiteralTypes1.ts, 59, 31)) +>MatchPair : Symbol(MatchPair, Decl(templateLiteralTypes1.ts, 51, 24)) + +type T24 = MatchPair<'[1,2,3,4]'>; // ['1', '2,3,4'] +>T24 : Symbol(T24, Decl(templateLiteralTypes1.ts, 60, 30)) +>MatchPair : Symbol(MatchPair, Decl(templateLiteralTypes1.ts, 51, 24)) + +type SnakeToCamelCase = +>SnakeToCamelCase : Symbol(SnakeToCamelCase, Decl(templateLiteralTypes1.ts, 61, 34)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 63, 22)) + + S extends `${infer T}_${infer U}` ? `${lowercase T}${SnakeToPascalCase}` : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 63, 22)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 64, 22)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 64, 33)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 64, 22)) +>SnakeToPascalCase : Symbol(SnakeToPascalCase, Decl(templateLiteralTypes1.ts, 66, 25)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 64, 33)) + + S extends `${infer T}` ? `${lowercase T}` : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 63, 22)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 65, 22)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 65, 22)) + + SnakeToPascalCase; +>SnakeToPascalCase : Symbol(SnakeToPascalCase, Decl(templateLiteralTypes1.ts, 66, 25)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 63, 22)) + +type SnakeToPascalCase = +>SnakeToPascalCase : Symbol(SnakeToPascalCase, Decl(templateLiteralTypes1.ts, 66, 25)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 68, 23)) + + string extends S ? string : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 68, 23)) + + S extends `${infer T}_${infer U}` ? `${capitalize `${lowercase T}`}${SnakeToPascalCase}` : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 68, 23)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 70, 22)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 70, 33)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 70, 22)) +>SnakeToPascalCase : Symbol(SnakeToPascalCase, Decl(templateLiteralTypes1.ts, 66, 25)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 70, 33)) + + S extends `${infer T}` ? `${capitalize `${lowercase T}`}` : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 68, 23)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 71, 22)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 71, 22)) + + never; + +type RR0 = SnakeToPascalCase<'hello_world_foo'>; // 'HelloWorldFoo' +>RR0 : Symbol(RR0, Decl(templateLiteralTypes1.ts, 72, 10)) +>SnakeToPascalCase : Symbol(SnakeToPascalCase, Decl(templateLiteralTypes1.ts, 66, 25)) + +type RR1 = SnakeToPascalCase<'FOO_BAR_BAZ'>; // 'FooBarBaz' +>RR1 : Symbol(RR1, Decl(templateLiteralTypes1.ts, 74, 48)) +>SnakeToPascalCase : Symbol(SnakeToPascalCase, Decl(templateLiteralTypes1.ts, 66, 25)) + +type RR2 = SnakeToCamelCase<'hello_world_foo'>; // 'helloWorldFoo' +>RR2 : Symbol(RR2, Decl(templateLiteralTypes1.ts, 75, 44)) +>SnakeToCamelCase : Symbol(SnakeToCamelCase, Decl(templateLiteralTypes1.ts, 61, 34)) + +type RR3 = SnakeToCamelCase<'FOO_BAR_BAZ'>; // 'fooBarBaz' +>RR3 : Symbol(RR3, Decl(templateLiteralTypes1.ts, 76, 47)) +>SnakeToCamelCase : Symbol(SnakeToCamelCase, Decl(templateLiteralTypes1.ts, 61, 34)) + +// Single character inference + +type FirstTwoAndRest = S extends `${infer A}${infer B}${infer R}` ? [`${A}${B}`, R] : unknown; +>FirstTwoAndRest : Symbol(FirstTwoAndRest, Decl(templateLiteralTypes1.ts, 77, 43)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 81, 21)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 81, 21)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 81, 59)) +>B : Symbol(B, Decl(templateLiteralTypes1.ts, 81, 69)) +>R : Symbol(R, Decl(templateLiteralTypes1.ts, 81, 79)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 81, 59)) +>B : Symbol(B, Decl(templateLiteralTypes1.ts, 81, 69)) +>R : Symbol(R, Decl(templateLiteralTypes1.ts, 81, 79)) + +type T25 = FirstTwoAndRest<'abcde'>; // ['ab', 'cde'] +>T25 : Symbol(T25, Decl(templateLiteralTypes1.ts, 81, 112)) +>FirstTwoAndRest : Symbol(FirstTwoAndRest, Decl(templateLiteralTypes1.ts, 77, 43)) + +type T26 = FirstTwoAndRest<'ab'>; // ['ab', ''] +>T26 : Symbol(T26, Decl(templateLiteralTypes1.ts, 83, 36)) +>FirstTwoAndRest : Symbol(FirstTwoAndRest, Decl(templateLiteralTypes1.ts, 77, 43)) + +type T27 = FirstTwoAndRest<'a'>; // unknown +>T27 : Symbol(T27, Decl(templateLiteralTypes1.ts, 84, 33)) +>FirstTwoAndRest : Symbol(FirstTwoAndRest, Decl(templateLiteralTypes1.ts, 77, 43)) + +type Capitalize = S extends `${infer H}${infer T}` ? `${uppercase H}${T}` : S; +>Capitalize : Symbol(Capitalize, Decl(templateLiteralTypes1.ts, 85, 32)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 87, 16)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 87, 16)) +>H : Symbol(H, Decl(templateLiteralTypes1.ts, 87, 54)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 87, 64)) +>H : Symbol(H, Decl(templateLiteralTypes1.ts, 87, 54)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 87, 64)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 87, 16)) + +type Uncapitalize = S extends `${infer H}${infer T}` ? `${lowercase H}${T}` : S; +>Uncapitalize : Symbol(Uncapitalize, Decl(templateLiteralTypes1.ts, 87, 96)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 88, 18)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 88, 18)) +>H : Symbol(H, Decl(templateLiteralTypes1.ts, 88, 56)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 88, 66)) +>H : Symbol(H, Decl(templateLiteralTypes1.ts, 88, 56)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 88, 66)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 88, 18)) + +type TC1 = Capitalize<'foo'>; // 'Foo' +>TC1 : Symbol(TC1, Decl(templateLiteralTypes1.ts, 88, 98)) +>Capitalize : Symbol(Capitalize, Decl(templateLiteralTypes1.ts, 85, 32)) + +type TC2 = Uncapitalize<'Foo'>; // 'foo' +>TC2 : Symbol(TC2, Decl(templateLiteralTypes1.ts, 90, 29)) +>Uncapitalize : Symbol(Uncapitalize, Decl(templateLiteralTypes1.ts, 87, 96)) + +type HexDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' |'8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'; +>HexDigit : Symbol(HexDigit, Decl(templateLiteralTypes1.ts, 91, 31)) + +type HexColor = +>HexColor : Symbol(HexColor, Decl(templateLiteralTypes1.ts, 93, 145)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 95, 14)) + + S extends `#${infer R1}${infer R2}${infer G1}${infer G2}${infer B1}${infer B2}` ? +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 95, 14)) +>R1 : Symbol(R1, Decl(templateLiteralTypes1.ts, 96, 23)) +>R2 : Symbol(R2, Decl(templateLiteralTypes1.ts, 96, 34)) +>G1 : Symbol(G1, Decl(templateLiteralTypes1.ts, 96, 45)) +>G2 : Symbol(G2, Decl(templateLiteralTypes1.ts, 96, 56)) +>B1 : Symbol(B1, Decl(templateLiteralTypes1.ts, 96, 67)) +>B2 : Symbol(B2, Decl(templateLiteralTypes1.ts, 96, 78)) + + [R1, R2, G1, G2, B1, B2] extends [HexDigit, HexDigit, HexDigit, HexDigit, HexDigit, HexDigit] ? +>R1 : Symbol(R1, Decl(templateLiteralTypes1.ts, 96, 23)) +>R2 : Symbol(R2, Decl(templateLiteralTypes1.ts, 96, 34)) +>G1 : Symbol(G1, Decl(templateLiteralTypes1.ts, 96, 45)) +>G2 : Symbol(G2, Decl(templateLiteralTypes1.ts, 96, 56)) +>B1 : Symbol(B1, Decl(templateLiteralTypes1.ts, 96, 67)) +>B2 : Symbol(B2, Decl(templateLiteralTypes1.ts, 96, 78)) +>HexDigit : Symbol(HexDigit, Decl(templateLiteralTypes1.ts, 91, 31)) +>HexDigit : Symbol(HexDigit, Decl(templateLiteralTypes1.ts, 91, 31)) +>HexDigit : Symbol(HexDigit, Decl(templateLiteralTypes1.ts, 91, 31)) +>HexDigit : Symbol(HexDigit, Decl(templateLiteralTypes1.ts, 91, 31)) +>HexDigit : Symbol(HexDigit, Decl(templateLiteralTypes1.ts, 91, 31)) +>HexDigit : Symbol(HexDigit, Decl(templateLiteralTypes1.ts, 91, 31)) + + S : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 95, 14)) + + never : + never; + +type TH1 = HexColor<'#8080FF'>; // '#8080FF' +>TH1 : Symbol(TH1, Decl(templateLiteralTypes1.ts, 100, 14)) +>HexColor : Symbol(HexColor, Decl(templateLiteralTypes1.ts, 93, 145)) + +type TH2 = HexColor<'#80c0ff'>; // '#80c0ff' +>TH2 : Symbol(TH2, Decl(templateLiteralTypes1.ts, 102, 31)) +>HexColor : Symbol(HexColor, Decl(templateLiteralTypes1.ts, 93, 145)) + +type TH3 = HexColor<'#8080F'>; // never +>TH3 : Symbol(TH3, Decl(templateLiteralTypes1.ts, 103, 31)) +>HexColor : Symbol(HexColor, Decl(templateLiteralTypes1.ts, 93, 145)) + +type TH4 = HexColor<'#8080FFF'>; // never +>TH4 : Symbol(TH4, Decl(templateLiteralTypes1.ts, 104, 30)) +>HexColor : Symbol(HexColor, Decl(templateLiteralTypes1.ts, 93, 145)) + +// Recursive inference + +type Trim = +>Trim : Symbol(Trim, Decl(templateLiteralTypes1.ts, 105, 32)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 109, 10)) + + S extends ` ${infer T}` ? Trim : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 109, 10)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 110, 23)) +>Trim : Symbol(Trim, Decl(templateLiteralTypes1.ts, 105, 32)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 110, 23)) + + S extends `${infer T} ` ? Trim : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 109, 10)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 111, 22)) +>Trim : Symbol(Trim, Decl(templateLiteralTypes1.ts, 105, 32)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 111, 22)) + + S; +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 109, 10)) + +type TR1 = Trim<'xx '>; // 'xx' +>TR1 : Symbol(TR1, Decl(templateLiteralTypes1.ts, 112, 6)) +>Trim : Symbol(Trim, Decl(templateLiteralTypes1.ts, 105, 32)) + +type TR2 = Trim<' xx'>; // 'xx' +>TR2 : Symbol(TR2, Decl(templateLiteralTypes1.ts, 114, 25)) +>Trim : Symbol(Trim, Decl(templateLiteralTypes1.ts, 105, 32)) + +type TR3 = Trim<' xx '>; // 'xx' +>TR3 : Symbol(TR3, Decl(templateLiteralTypes1.ts, 115, 25)) +>Trim : Symbol(Trim, Decl(templateLiteralTypes1.ts, 105, 32)) + +type Split = +>Split : Symbol(Split, Decl(templateLiteralTypes1.ts, 116, 28)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 118, 11)) +>D : Symbol(D, Decl(templateLiteralTypes1.ts, 118, 28)) + + string extends S ? string[] : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 118, 11)) + + S extends '' ? [] : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 118, 11)) + + S extends `${infer T}${D}${infer U}` ? [T, ...Split] : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 118, 11)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 121, 22)) +>D : Symbol(D, Decl(templateLiteralTypes1.ts, 118, 28)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 121, 36)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 121, 22)) +>Split : Symbol(Split, Decl(templateLiteralTypes1.ts, 116, 28)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 121, 36)) +>D : Symbol(D, Decl(templateLiteralTypes1.ts, 118, 28)) + + [S]; +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 118, 11)) + +type T40 = Split<'foo', '.'>; // ['foo'] +>T40 : Symbol(T40, Decl(templateLiteralTypes1.ts, 122, 8)) +>Split : Symbol(Split, Decl(templateLiteralTypes1.ts, 116, 28)) + +type T41 = Split<'foo.bar.baz', '.'>; // ['foo', 'bar', 'baz'] +>T41 : Symbol(T41, Decl(templateLiteralTypes1.ts, 124, 29)) +>Split : Symbol(Split, Decl(templateLiteralTypes1.ts, 116, 28)) + +type T42 = Split<'foo.bar', ''>; // ['f', 'o', 'o', '.', 'b', 'a', 'r'] +>T42 : Symbol(T42, Decl(templateLiteralTypes1.ts, 125, 37)) +>Split : Symbol(Split, Decl(templateLiteralTypes1.ts, 116, 28)) + +type T43 = Split; // string[] +>T43 : Symbol(T43, Decl(templateLiteralTypes1.ts, 126, 32)) +>Split : Symbol(Split, Decl(templateLiteralTypes1.ts, 116, 28)) + +// Inference and property name paths + +declare function getProp(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; +>getProp : Symbol(getProp, Decl(templateLiteralTypes1.ts, 127, 27), Decl(templateLiteralTypes1.ts, 131, 177), Decl(templateLiteralTypes1.ts, 132, 130), Decl(templateLiteralTypes1.ts, 133, 82)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 131, 25)) +>P0 : Symbol(P0, Decl(templateLiteralTypes1.ts, 131, 27)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 131, 25)) +>P1 : Symbol(P1, Decl(templateLiteralTypes1.ts, 131, 56)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 131, 25)) +>P0 : Symbol(P0, Decl(templateLiteralTypes1.ts, 131, 27)) +>P2 : Symbol(P2, Decl(templateLiteralTypes1.ts, 131, 89)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 131, 25)) +>P0 : Symbol(P0, Decl(templateLiteralTypes1.ts, 131, 27)) +>P1 : Symbol(P1, Decl(templateLiteralTypes1.ts, 131, 56)) +>obj : Symbol(obj, Decl(templateLiteralTypes1.ts, 131, 127)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 131, 25)) +>path : Symbol(path, Decl(templateLiteralTypes1.ts, 131, 134)) +>P0 : Symbol(P0, Decl(templateLiteralTypes1.ts, 131, 27)) +>P1 : Symbol(P1, Decl(templateLiteralTypes1.ts, 131, 56)) +>P2 : Symbol(P2, Decl(templateLiteralTypes1.ts, 131, 89)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 131, 25)) +>P0 : Symbol(P0, Decl(templateLiteralTypes1.ts, 131, 27)) +>P1 : Symbol(P1, Decl(templateLiteralTypes1.ts, 131, 56)) +>P2 : Symbol(P2, Decl(templateLiteralTypes1.ts, 131, 89)) + +declare function getProp(obj: T, path: `${P0}.${P1}`): T[P0][P1]; +>getProp : Symbol(getProp, Decl(templateLiteralTypes1.ts, 127, 27), Decl(templateLiteralTypes1.ts, 131, 177), Decl(templateLiteralTypes1.ts, 132, 130), Decl(templateLiteralTypes1.ts, 133, 82)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 132, 25)) +>P0 : Symbol(P0, Decl(templateLiteralTypes1.ts, 132, 27)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 132, 25)) +>P1 : Symbol(P1, Decl(templateLiteralTypes1.ts, 132, 56)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 132, 25)) +>P0 : Symbol(P0, Decl(templateLiteralTypes1.ts, 132, 27)) +>obj : Symbol(obj, Decl(templateLiteralTypes1.ts, 132, 90)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 132, 25)) +>path : Symbol(path, Decl(templateLiteralTypes1.ts, 132, 97)) +>P0 : Symbol(P0, Decl(templateLiteralTypes1.ts, 132, 27)) +>P1 : Symbol(P1, Decl(templateLiteralTypes1.ts, 132, 56)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 132, 25)) +>P0 : Symbol(P0, Decl(templateLiteralTypes1.ts, 132, 27)) +>P1 : Symbol(P1, Decl(templateLiteralTypes1.ts, 132, 56)) + +declare function getProp(obj: T, path: P0): T[P0]; +>getProp : Symbol(getProp, Decl(templateLiteralTypes1.ts, 127, 27), Decl(templateLiteralTypes1.ts, 131, 177), Decl(templateLiteralTypes1.ts, 132, 130), Decl(templateLiteralTypes1.ts, 133, 82)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 133, 25)) +>P0 : Symbol(P0, Decl(templateLiteralTypes1.ts, 133, 27)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 133, 25)) +>obj : Symbol(obj, Decl(templateLiteralTypes1.ts, 133, 57)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 133, 25)) +>path : Symbol(path, Decl(templateLiteralTypes1.ts, 133, 64)) +>P0 : Symbol(P0, Decl(templateLiteralTypes1.ts, 133, 27)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 133, 25)) +>P0 : Symbol(P0, Decl(templateLiteralTypes1.ts, 133, 27)) + +declare function getProp(obj: object, path: string): unknown; +>getProp : Symbol(getProp, Decl(templateLiteralTypes1.ts, 127, 27), Decl(templateLiteralTypes1.ts, 131, 177), Decl(templateLiteralTypes1.ts, 132, 130), Decl(templateLiteralTypes1.ts, 133, 82)) +>obj : Symbol(obj, Decl(templateLiteralTypes1.ts, 134, 25)) +>path : Symbol(path, Decl(templateLiteralTypes1.ts, 134, 37)) + +let p1 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a'); +>p1 : Symbol(p1, Decl(templateLiteralTypes1.ts, 136, 3)) +>getProp : Symbol(getProp, Decl(templateLiteralTypes1.ts, 127, 27), Decl(templateLiteralTypes1.ts, 131, 177), Decl(templateLiteralTypes1.ts, 132, 130), Decl(templateLiteralTypes1.ts, 133, 82)) +>a : Symbol(a, Decl(templateLiteralTypes1.ts, 136, 18)) +>b : Symbol(b, Decl(templateLiteralTypes1.ts, 136, 23)) +>c : Symbol(c, Decl(templateLiteralTypes1.ts, 136, 28)) +>d : Symbol(d, Decl(templateLiteralTypes1.ts, 136, 34)) + +let p2 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a.b'); +>p2 : Symbol(p2, Decl(templateLiteralTypes1.ts, 137, 3)) +>getProp : Symbol(getProp, Decl(templateLiteralTypes1.ts, 127, 27), Decl(templateLiteralTypes1.ts, 131, 177), Decl(templateLiteralTypes1.ts, 132, 130), Decl(templateLiteralTypes1.ts, 133, 82)) +>a : Symbol(a, Decl(templateLiteralTypes1.ts, 137, 18)) +>b : Symbol(b, Decl(templateLiteralTypes1.ts, 137, 23)) +>c : Symbol(c, Decl(templateLiteralTypes1.ts, 137, 28)) +>d : Symbol(d, Decl(templateLiteralTypes1.ts, 137, 34)) + +let p3 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a.b.d'); +>p3 : Symbol(p3, Decl(templateLiteralTypes1.ts, 138, 3)) +>getProp : Symbol(getProp, Decl(templateLiteralTypes1.ts, 127, 27), Decl(templateLiteralTypes1.ts, 131, 177), Decl(templateLiteralTypes1.ts, 132, 130), Decl(templateLiteralTypes1.ts, 133, 82)) +>a : Symbol(a, Decl(templateLiteralTypes1.ts, 138, 18)) +>b : Symbol(b, Decl(templateLiteralTypes1.ts, 138, 23)) +>c : Symbol(c, Decl(templateLiteralTypes1.ts, 138, 28)) +>d : Symbol(d, Decl(templateLiteralTypes1.ts, 138, 34)) + +type PropType = +>PropType : Symbol(PropType, Decl(templateLiteralTypes1.ts, 138, 69)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 140, 14)) +>Path : Symbol(Path, Decl(templateLiteralTypes1.ts, 140, 16)) + + string extends Path ? unknown : +>Path : Symbol(Path, Decl(templateLiteralTypes1.ts, 140, 16)) + + Path extends keyof T ? T[Path] : +>Path : Symbol(Path, Decl(templateLiteralTypes1.ts, 140, 16)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 140, 14)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 140, 14)) +>Path : Symbol(Path, Decl(templateLiteralTypes1.ts, 140, 16)) + + Path extends `${infer K}.${infer R}` ? K extends keyof T ? PropType : unknown : +>Path : Symbol(Path, Decl(templateLiteralTypes1.ts, 140, 16)) +>K : Symbol(K, Decl(templateLiteralTypes1.ts, 143, 25)) +>R : Symbol(R, Decl(templateLiteralTypes1.ts, 143, 36)) +>K : Symbol(K, Decl(templateLiteralTypes1.ts, 143, 25)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 140, 14)) +>PropType : Symbol(PropType, Decl(templateLiteralTypes1.ts, 138, 69)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 140, 14)) +>K : Symbol(K, Decl(templateLiteralTypes1.ts, 143, 25)) +>R : Symbol(R, Decl(templateLiteralTypes1.ts, 143, 36)) + + unknown; + +declare function getPropValue(obj: T, path: P): PropType; +>getPropValue : Symbol(getPropValue, Decl(templateLiteralTypes1.ts, 144, 12)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 146, 30)) +>P : Symbol(P, Decl(templateLiteralTypes1.ts, 146, 32)) +>obj : Symbol(obj, Decl(templateLiteralTypes1.ts, 146, 51)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 146, 30)) +>path : Symbol(path, Decl(templateLiteralTypes1.ts, 146, 58)) +>P : Symbol(P, Decl(templateLiteralTypes1.ts, 146, 32)) +>PropType : Symbol(PropType, Decl(templateLiteralTypes1.ts, 138, 69)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 146, 30)) +>P : Symbol(P, Decl(templateLiteralTypes1.ts, 146, 32)) + +declare const s: string; +>s : Symbol(s, Decl(templateLiteralTypes1.ts, 147, 13)) + +const obj = { a: { b: {c: 42, d: 'hello' }}}; +>obj : Symbol(obj, Decl(templateLiteralTypes1.ts, 149, 5)) +>a : Symbol(a, Decl(templateLiteralTypes1.ts, 149, 13)) +>b : Symbol(b, Decl(templateLiteralTypes1.ts, 149, 18)) +>c : Symbol(c, Decl(templateLiteralTypes1.ts, 149, 23)) +>d : Symbol(d, Decl(templateLiteralTypes1.ts, 149, 29)) + +getPropValue(obj, 'a'); // { b: {c: number, d: string } } +>getPropValue : Symbol(getPropValue, Decl(templateLiteralTypes1.ts, 144, 12)) +>obj : Symbol(obj, Decl(templateLiteralTypes1.ts, 149, 5)) + +getPropValue(obj, 'a.b'); // {c: number, d: string } +>getPropValue : Symbol(getPropValue, Decl(templateLiteralTypes1.ts, 144, 12)) +>obj : Symbol(obj, Decl(templateLiteralTypes1.ts, 149, 5)) + +getPropValue(obj, 'a.b.d'); // string +>getPropValue : Symbol(getPropValue, Decl(templateLiteralTypes1.ts, 144, 12)) +>obj : Symbol(obj, Decl(templateLiteralTypes1.ts, 149, 5)) + +getPropValue(obj, 'a.b.x'); // unknown +>getPropValue : Symbol(getPropValue, Decl(templateLiteralTypes1.ts, 144, 12)) +>obj : Symbol(obj, Decl(templateLiteralTypes1.ts, 149, 5)) + +getPropValue(obj, s); // unknown +>getPropValue : Symbol(getPropValue, Decl(templateLiteralTypes1.ts, 144, 12)) +>obj : Symbol(obj, Decl(templateLiteralTypes1.ts, 149, 5)) +>s : Symbol(s, Decl(templateLiteralTypes1.ts, 147, 13)) + +// Infer type variables in template literals have string constraint + +type S1 = T extends `foo${infer U}bar` ? S2 : never; +>S1 : Symbol(S1, Decl(templateLiteralTypes1.ts, 155, 21)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 159, 8)) +>T : Symbol(T, Decl(templateLiteralTypes1.ts, 159, 8)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 159, 34)) +>S2 : Symbol(S2, Decl(templateLiteralTypes1.ts, 159, 58)) +>U : Symbol(U, Decl(templateLiteralTypes1.ts, 159, 34)) + +type S2 = S; +>S2 : Symbol(S2, Decl(templateLiteralTypes1.ts, 159, 58)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 160, 8)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 160, 8)) + +// Batched single character inferences for lower recursion depth + +type Chars = +>Chars : Symbol(Chars, Decl(templateLiteralTypes1.ts, 160, 30)) +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 164, 11)) + + string extends S ? string[] : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 164, 11)) + + S extends `${infer C0}${infer C1}${infer C2}${infer C3}${infer C4}${infer C5}${infer C6}${infer C7}${infer C8}${infer C9}${infer R}` ? [C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, ...Chars] : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 164, 11)) +>C0 : Symbol(C0, Decl(templateLiteralTypes1.ts, 166, 22)) +>C1 : Symbol(C1, Decl(templateLiteralTypes1.ts, 166, 33)) +>C2 : Symbol(C2, Decl(templateLiteralTypes1.ts, 166, 44)) +>C3 : Symbol(C3, Decl(templateLiteralTypes1.ts, 166, 55)) +>C4 : Symbol(C4, Decl(templateLiteralTypes1.ts, 166, 66)) +>C5 : Symbol(C5, Decl(templateLiteralTypes1.ts, 166, 77)) +>C6 : Symbol(C6, Decl(templateLiteralTypes1.ts, 166, 88)) +>C7 : Symbol(C7, Decl(templateLiteralTypes1.ts, 166, 99)) +>C8 : Symbol(C8, Decl(templateLiteralTypes1.ts, 166, 110)) +>C9 : Symbol(C9, Decl(templateLiteralTypes1.ts, 166, 121)) +>R : Symbol(R, Decl(templateLiteralTypes1.ts, 166, 132)) +>C0 : Symbol(C0, Decl(templateLiteralTypes1.ts, 166, 22)) +>C1 : Symbol(C1, Decl(templateLiteralTypes1.ts, 166, 33)) +>C2 : Symbol(C2, Decl(templateLiteralTypes1.ts, 166, 44)) +>C3 : Symbol(C3, Decl(templateLiteralTypes1.ts, 166, 55)) +>C4 : Symbol(C4, Decl(templateLiteralTypes1.ts, 166, 66)) +>C5 : Symbol(C5, Decl(templateLiteralTypes1.ts, 166, 77)) +>C6 : Symbol(C6, Decl(templateLiteralTypes1.ts, 166, 88)) +>C7 : Symbol(C7, Decl(templateLiteralTypes1.ts, 166, 99)) +>C8 : Symbol(C8, Decl(templateLiteralTypes1.ts, 166, 110)) +>C9 : Symbol(C9, Decl(templateLiteralTypes1.ts, 166, 121)) +>Chars : Symbol(Chars, Decl(templateLiteralTypes1.ts, 160, 30)) +>R : Symbol(R, Decl(templateLiteralTypes1.ts, 166, 132)) + + S extends `${infer C}${infer R}` ? [C, ...Chars] : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 164, 11)) +>C : Symbol(C, Decl(templateLiteralTypes1.ts, 167, 22)) +>R : Symbol(R, Decl(templateLiteralTypes1.ts, 167, 32)) +>C : Symbol(C, Decl(templateLiteralTypes1.ts, 167, 22)) +>Chars : Symbol(Chars, Decl(templateLiteralTypes1.ts, 160, 30)) +>R : Symbol(R, Decl(templateLiteralTypes1.ts, 167, 32)) + + S extends '' ? [] : +>S : Symbol(S, Decl(templateLiteralTypes1.ts, 164, 11)) + + never; + +type L1 = Chars<'FooBarBazThisIsALongerString'>; // ['F', 'o', 'o', 'B', 'a', 'r', ...] +>L1 : Symbol(L1, Decl(templateLiteralTypes1.ts, 169, 10)) +>Chars : Symbol(Chars, Decl(templateLiteralTypes1.ts, 160, 30)) + +// Cross product unions limited to 100,000 constituents + +type A = any; +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) + +type U1 = {a1:A} | {b1:A} | {c1:A} | {d1:A} | {e1:A} | {f1:A} | {g1:A} | {h1:A} | {i1:A} | {j1:A}; +>U1 : Symbol(U1, Decl(templateLiteralTypes1.ts, 175, 13)) +>a1 : Symbol(a1, Decl(templateLiteralTypes1.ts, 177, 11)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>b1 : Symbol(b1, Decl(templateLiteralTypes1.ts, 177, 20)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>c1 : Symbol(c1, Decl(templateLiteralTypes1.ts, 177, 29)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>d1 : Symbol(d1, Decl(templateLiteralTypes1.ts, 177, 38)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>e1 : Symbol(e1, Decl(templateLiteralTypes1.ts, 177, 47)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>f1 : Symbol(f1, Decl(templateLiteralTypes1.ts, 177, 56)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>g1 : Symbol(g1, Decl(templateLiteralTypes1.ts, 177, 65)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>h1 : Symbol(h1, Decl(templateLiteralTypes1.ts, 177, 74)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>i1 : Symbol(i1, Decl(templateLiteralTypes1.ts, 177, 83)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>j1 : Symbol(j1, Decl(templateLiteralTypes1.ts, 177, 92)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) + +type U2 = {a2:A} | {b2:A} | {c2:A} | {d2:A} | {e2:A} | {f2:A} | {g2:A} | {h2:A} | {i2:A} | {j2:A}; +>U2 : Symbol(U2, Decl(templateLiteralTypes1.ts, 177, 98)) +>a2 : Symbol(a2, Decl(templateLiteralTypes1.ts, 178, 11)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>b2 : Symbol(b2, Decl(templateLiteralTypes1.ts, 178, 20)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>c2 : Symbol(c2, Decl(templateLiteralTypes1.ts, 178, 29)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>d2 : Symbol(d2, Decl(templateLiteralTypes1.ts, 178, 38)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>e2 : Symbol(e2, Decl(templateLiteralTypes1.ts, 178, 47)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>f2 : Symbol(f2, Decl(templateLiteralTypes1.ts, 178, 56)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>g2 : Symbol(g2, Decl(templateLiteralTypes1.ts, 178, 65)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>h2 : Symbol(h2, Decl(templateLiteralTypes1.ts, 178, 74)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>i2 : Symbol(i2, Decl(templateLiteralTypes1.ts, 178, 83)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>j2 : Symbol(j2, Decl(templateLiteralTypes1.ts, 178, 92)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) + +type U3 = {a3:A} | {b3:A} | {c3:A} | {d3:A} | {e3:A} | {f3:A} | {g3:A} | {h3:A} | {i3:A} | {j3:A}; +>U3 : Symbol(U3, Decl(templateLiteralTypes1.ts, 178, 98)) +>a3 : Symbol(a3, Decl(templateLiteralTypes1.ts, 179, 11)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>b3 : Symbol(b3, Decl(templateLiteralTypes1.ts, 179, 20)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>c3 : Symbol(c3, Decl(templateLiteralTypes1.ts, 179, 29)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>d3 : Symbol(d3, Decl(templateLiteralTypes1.ts, 179, 38)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>e3 : Symbol(e3, Decl(templateLiteralTypes1.ts, 179, 47)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>f3 : Symbol(f3, Decl(templateLiteralTypes1.ts, 179, 56)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>g3 : Symbol(g3, Decl(templateLiteralTypes1.ts, 179, 65)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>h3 : Symbol(h3, Decl(templateLiteralTypes1.ts, 179, 74)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>i3 : Symbol(i3, Decl(templateLiteralTypes1.ts, 179, 83)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>j3 : Symbol(j3, Decl(templateLiteralTypes1.ts, 179, 92)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) + +type U4 = {a4:A} | {b4:A} | {c4:A} | {d4:A} | {e4:A} | {f4:A} | {g4:A} | {h4:A} | {i4:A} | {j4:A}; +>U4 : Symbol(U4, Decl(templateLiteralTypes1.ts, 179, 98)) +>a4 : Symbol(a4, Decl(templateLiteralTypes1.ts, 180, 11)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>b4 : Symbol(b4, Decl(templateLiteralTypes1.ts, 180, 20)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>c4 : Symbol(c4, Decl(templateLiteralTypes1.ts, 180, 29)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>d4 : Symbol(d4, Decl(templateLiteralTypes1.ts, 180, 38)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>e4 : Symbol(e4, Decl(templateLiteralTypes1.ts, 180, 47)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>f4 : Symbol(f4, Decl(templateLiteralTypes1.ts, 180, 56)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>g4 : Symbol(g4, Decl(templateLiteralTypes1.ts, 180, 65)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>h4 : Symbol(h4, Decl(templateLiteralTypes1.ts, 180, 74)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>i4 : Symbol(i4, Decl(templateLiteralTypes1.ts, 180, 83)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>j4 : Symbol(j4, Decl(templateLiteralTypes1.ts, 180, 92)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) + +type U5 = {a5:A} | {b5:A} | {c5:A} | {d5:A} | {e5:A} | {f5:A} | {g5:A} | {h5:A} | {i5:A} | {j5:A}; +>U5 : Symbol(U5, Decl(templateLiteralTypes1.ts, 180, 98)) +>a5 : Symbol(a5, Decl(templateLiteralTypes1.ts, 181, 11)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>b5 : Symbol(b5, Decl(templateLiteralTypes1.ts, 181, 20)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>c5 : Symbol(c5, Decl(templateLiteralTypes1.ts, 181, 29)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>d5 : Symbol(d5, Decl(templateLiteralTypes1.ts, 181, 38)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>e5 : Symbol(e5, Decl(templateLiteralTypes1.ts, 181, 47)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>f5 : Symbol(f5, Decl(templateLiteralTypes1.ts, 181, 56)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>g5 : Symbol(g5, Decl(templateLiteralTypes1.ts, 181, 65)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>h5 : Symbol(h5, Decl(templateLiteralTypes1.ts, 181, 74)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>i5 : Symbol(i5, Decl(templateLiteralTypes1.ts, 181, 83)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) +>j5 : Symbol(j5, Decl(templateLiteralTypes1.ts, 181, 92)) +>A : Symbol(A, Decl(templateLiteralTypes1.ts, 171, 48)) + +type U100000 = U1 & U2 & U3 & U4 & U5; // Error +>U100000 : Symbol(U100000, Decl(templateLiteralTypes1.ts, 181, 98)) +>U1 : Symbol(U1, Decl(templateLiteralTypes1.ts, 175, 13)) +>U2 : Symbol(U2, Decl(templateLiteralTypes1.ts, 177, 98)) +>U3 : Symbol(U3, Decl(templateLiteralTypes1.ts, 178, 98)) +>U4 : Symbol(U4, Decl(templateLiteralTypes1.ts, 179, 98)) +>U5 : Symbol(U5, Decl(templateLiteralTypes1.ts, 180, 98)) + +type Digits = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; +>Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 183, 38)) + +type D100000 = `${Digits}${Digits}${Digits}${Digits}${Digits}`; // Error +>D100000 : Symbol(D100000, Decl(templateLiteralTypes1.ts, 185, 52)) +>Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 183, 38)) +>Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 183, 38)) +>Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 183, 38)) +>Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 183, 38)) +>Digits : Symbol(Digits, Decl(templateLiteralTypes1.ts, 183, 38)) + +type TDigits = [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9]; +>TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 187, 63)) + +type T100000 = [...TDigits, ...TDigits, ...TDigits, ...TDigits, ...TDigits]; // Error +>T100000 : Symbol(T100000, Decl(templateLiteralTypes1.ts, 189, 73)) +>TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 187, 63)) +>TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 187, 63)) +>TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 187, 63)) +>TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 187, 63)) +>TDigits : Symbol(TDigits, Decl(templateLiteralTypes1.ts, 187, 63)) + diff --git a/tests/baselines/reference/templateLiteralTypes1.types b/tests/baselines/reference/templateLiteralTypes1.types new file mode 100644 index 0000000000000..400b77b612da3 --- /dev/null +++ b/tests/baselines/reference/templateLiteralTypes1.types @@ -0,0 +1,496 @@ +=== tests/cases/conformance/types/literal/templateLiteralTypes1.ts === +// Template types example from #12754 + +const createScopedActionType = (scope: S) => (type: T) => `${scope}/${type}` as `${S}/${T}`; +>createScopedActionType : (scope: S) => (type: T) => `${S}/${T}` +>(scope: S) => (type: T) => `${scope}/${type}` as `${S}/${T}` : (scope: S) => (type: T) => `${S}/${T}` +>scope : S +>(type: T) => `${scope}/${type}` as `${S}/${T}` : (type: T) => `${S}/${T}` +>type : T +>`${scope}/${type}` as `${S}/${T}` : `${S}/${T}` +>`${scope}/${type}` : string +>scope : S +>type : T + +const createActionInMyScope = createScopedActionType("MyScope"); // (type: T) => `MyScope/${T}` +>createActionInMyScope : (type: T) => `MyScope/${T}` +>createScopedActionType("MyScope") : (type: T) => `MyScope/${T}` +>createScopedActionType : (scope: S) => (type: T) => `${S}/${T}` +>"MyScope" : "MyScope" + +const MY_ACTION = createActionInMyScope("MY_ACTION"); // 'MyScope/MY_ACTION' +>MY_ACTION : "MyScope/MY_ACTION" +>createActionInMyScope("MY_ACTION") : "MyScope/MY_ACTION" +>createActionInMyScope : (type: T) => `MyScope/${T}` +>"MY_ACTION" : "MY_ACTION" + +// Union types are distributed over template types + +type EventName = `${S}Changed`; +>EventName : `${S}Changed` + +type EN1 = EventName<'Foo' | 'Bar' | 'Baz'>; +>EN1 : "FooChanged" | "BarChanged" | "BazChanged" + +type Loc = `${'top' | 'middle' | 'bottom'}-${'left' | 'center' | 'right'}`; +>Loc : "top-left" | "top-center" | "top-right" | "middle-left" | "middle-center" | "middle-right" | "bottom-left" | "bottom-center" | "bottom-right" + +// Primitive literal types can be spread into templates + +type ToString = `${T}`; +>ToString : `${T}` + +type TS1 = ToString<'abc' | 42 | true | -1234n>; +>TS1 : "abc" | "true" | "42" | "-1234" +>true : true +>-1234n : -1234n +>1234n : 1234n + +// Casing modifiers + +type Cases = `${uppercase T} ${lowercase T} ${capitalize T} ${uncapitalize T}`; +>Cases : `${uppercase T} ${lowercase T} ${capitalize T} ${uncapitalize T}` + +type TCA1 = Cases<'bar'>; // 'BAR bar Bar bar' +>TCA1 : "BAR bar Bar bar" + +type TCA2 = Cases<'BAR'>; // 'BAR bar BAR bAR' +>TCA2 : "BAR bar BAR bAR" + +// Assignability + +function test(name: `get${capitalize T}`) { +>test : (name: `get${capitalize T}`) => void +>name : `get${capitalize T}` + + let s1: string = name; +>s1 : string +>name : `get${capitalize T}` + + let s2: 'getFoo' | 'getBar' = name; +>s2 : "getFoo" | "getBar" +>name : `get${capitalize T}` +} + +function fa1(x: T, y: { [P in keyof T]: T[P] }, z: { [P in keyof T & string as `p_${P}`]: T[P] }) { +>fa1 : (x: T, y: { [P in keyof T]: T[P]; }, z: { [P in keyof T & string as `p_${P}`]: T[P]; }) => void +>x : T +>y : { [P in keyof T]: T[P]; } +>z : { [P in keyof T & string as `p_${P}`]: T[P]; } + + y = x; +>y = x : T +>y : { [P in keyof T]: T[P]; } +>x : T + + z = x; // Error +>z = x : T +>z : { [P in keyof T & string as `p_${P}`]: T[P]; } +>x : T +} + +function fa2(x: { [P in B as `p_${P}`]: T }, y: { [Q in A as `p_${Q}`]: U }) { +>fa2 : (x: { [P in B as `p_${P}`]: T; }, y: { [Q in A as `p_${Q}`]: U; }) => void +>x : { [P in B as `p_${P}`]: T; } +>y : { [Q in A as `p_${Q}`]: U; } + + x = y; +>x = y : { [Q in A as `p_${Q}`]: U; } +>x : { [P in B as `p_${P}`]: T; } +>y : { [Q in A as `p_${Q}`]: U; } + + y = x; // Error +>y = x : { [P in B as `p_${P}`]: T; } +>y : { [Q in A as `p_${Q}`]: U; } +>x : { [P in B as `p_${P}`]: T; } +} + +// String transformations using recursive conditional types + +type Join = +>Join : Join + + T extends [] ? '' : + T extends [unknown] ? `${T[0]}` : + T extends [unknown, ...infer U] ? `${T[0]}${D}${Join}` : + string; + +type TJ1 = Join<[1, 2, 3, 4], '.'> +>TJ1 : "1.2.3.4" + +type TJ2 = Join<['foo', 'bar', 'baz'], '-'>; +>TJ2 : "foo-bar-baz" + +type TJ3 = Join<[], '.'> +>TJ3 : "" + +// Inference based on delimiters + +type MatchPair = S extends `[${infer A},${infer B}]` ? [A, B] : unknown; +>MatchPair : MatchPair + +type T20 = MatchPair<'[1,2]'>; // ['1', '2'] +>T20 : ["1", "2"] + +type T21 = MatchPair<'[foo,bar]'>; // ['foo', 'bar'] +>T21 : ["foo", "bar"] + +type T22 = MatchPair<' [1,2]'>; // unknown +>T22 : unknown + +type T23 = MatchPair<'[123]'>; // unknown +>T23 : unknown + +type T24 = MatchPair<'[1,2,3,4]'>; // ['1', '2,3,4'] +>T24 : ["1", "2,3,4"] + +type SnakeToCamelCase = +>SnakeToCamelCase : SnakeToCamelCase + + S extends `${infer T}_${infer U}` ? `${lowercase T}${SnakeToPascalCase}` : + S extends `${infer T}` ? `${lowercase T}` : + SnakeToPascalCase; + +type SnakeToPascalCase = +>SnakeToPascalCase : SnakeToPascalCase + + string extends S ? string : + S extends `${infer T}_${infer U}` ? `${capitalize `${lowercase T}`}${SnakeToPascalCase}` : + S extends `${infer T}` ? `${capitalize `${lowercase T}`}` : + never; + +type RR0 = SnakeToPascalCase<'hello_world_foo'>; // 'HelloWorldFoo' +>RR0 : "HelloWorldFoo" + +type RR1 = SnakeToPascalCase<'FOO_BAR_BAZ'>; // 'FooBarBaz' +>RR1 : "FooBarBaz" + +type RR2 = SnakeToCamelCase<'hello_world_foo'>; // 'helloWorldFoo' +>RR2 : "helloWorldFoo" + +type RR3 = SnakeToCamelCase<'FOO_BAR_BAZ'>; // 'fooBarBaz' +>RR3 : "fooBarBaz" + +// Single character inference + +type FirstTwoAndRest = S extends `${infer A}${infer B}${infer R}` ? [`${A}${B}`, R] : unknown; +>FirstTwoAndRest : FirstTwoAndRest + +type T25 = FirstTwoAndRest<'abcde'>; // ['ab', 'cde'] +>T25 : ["ab", "cde"] + +type T26 = FirstTwoAndRest<'ab'>; // ['ab', ''] +>T26 : ["ab", ""] + +type T27 = FirstTwoAndRest<'a'>; // unknown +>T27 : unknown + +type Capitalize = S extends `${infer H}${infer T}` ? `${uppercase H}${T}` : S; +>Capitalize : Capitalize + +type Uncapitalize = S extends `${infer H}${infer T}` ? `${lowercase H}${T}` : S; +>Uncapitalize : Uncapitalize + +type TC1 = Capitalize<'foo'>; // 'Foo' +>TC1 : "Foo" + +type TC2 = Uncapitalize<'Foo'>; // 'foo' +>TC2 : "foo" + +type HexDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' |'8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'; +>HexDigit : HexDigit + +type HexColor = +>HexColor : HexColor + + S extends `#${infer R1}${infer R2}${infer G1}${infer G2}${infer B1}${infer B2}` ? + [R1, R2, G1, G2, B1, B2] extends [HexDigit, HexDigit, HexDigit, HexDigit, HexDigit, HexDigit] ? + S : + never : + never; + +type TH1 = HexColor<'#8080FF'>; // '#8080FF' +>TH1 : "#8080FF" + +type TH2 = HexColor<'#80c0ff'>; // '#80c0ff' +>TH2 : "#80c0ff" + +type TH3 = HexColor<'#8080F'>; // never +>TH3 : never + +type TH4 = HexColor<'#8080FFF'>; // never +>TH4 : never + +// Recursive inference + +type Trim = +>Trim : Trim + + S extends ` ${infer T}` ? Trim : + S extends `${infer T} ` ? Trim : + S; + +type TR1 = Trim<'xx '>; // 'xx' +>TR1 : "xx" + +type TR2 = Trim<' xx'>; // 'xx' +>TR2 : "xx" + +type TR3 = Trim<' xx '>; // 'xx' +>TR3 : "xx" + +type Split = +>Split : Split + + string extends S ? string[] : + S extends '' ? [] : + S extends `${infer T}${D}${infer U}` ? [T, ...Split] : + [S]; + +type T40 = Split<'foo', '.'>; // ['foo'] +>T40 : ["foo"] + +type T41 = Split<'foo.bar.baz', '.'>; // ['foo', 'bar', 'baz'] +>T41 : ["foo", "bar", "baz"] + +type T42 = Split<'foo.bar', ''>; // ['f', 'o', 'o', '.', 'b', 'a', 'r'] +>T42 : ["f", "o", "o", ".", "b", "a", "r"] + +type T43 = Split; // string[] +>T43 : string[] + +// Inference and property name paths + +declare function getProp(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; +>getProp : { (obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; (obj: T, path: `${P0}.${P1}`): T[P0][P1]; (obj: T, path: P0): T[P0]; (obj: object, path: string): unknown; } +>obj : T +>path : `${P0}.${P1}.${P2}` + +declare function getProp(obj: T, path: `${P0}.${P1}`): T[P0][P1]; +>getProp : { (obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; (obj: T, path: `${P0}.${P1}`): T[P0][P1]; (obj: T, path: P0): T[P0]; (obj: object, path: string): unknown; } +>obj : T +>path : `${P0}.${P1}` + +declare function getProp(obj: T, path: P0): T[P0]; +>getProp : { (obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; (obj: T, path: `${P0}.${P1}`): T[P0][P1]; (obj: T, path: P0): T[P0]; (obj: object, path: string): unknown; } +>obj : T +>path : P0 + +declare function getProp(obj: object, path: string): unknown; +>getProp : { (obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; (obj: T, path: `${P0}.${P1}`): T[P0][P1]; (obj: T, path: P0): T[P0]; (obj: object, path: string): unknown; } +>obj : object +>path : string + +let p1 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a'); +>p1 : { readonly b: { readonly c: 42; readonly d: "hello"; }; } +>getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a') : { readonly b: { readonly c: 42; readonly d: "hello"; }; } +>getProp : { (obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; (obj: T, path: `${P0}.${P1}`): T[P0][P1]; (obj: T, path: P0): T[P0]; (obj: object, path: string): unknown; } +>{ a: { b: {c: 42, d: 'hello' }}} as const : { readonly a: { readonly b: { readonly c: 42; readonly d: "hello"; }; }; } +>{ a: { b: {c: 42, d: 'hello' }}} : { readonly a: { readonly b: { readonly c: 42; readonly d: "hello"; }; }; } +>a : { readonly b: { readonly c: 42; readonly d: "hello"; }; } +>{ b: {c: 42, d: 'hello' }} : { readonly b: { readonly c: 42; readonly d: "hello"; }; } +>b : { readonly c: 42; readonly d: "hello"; } +>{c: 42, d: 'hello' } : { readonly c: 42; readonly d: "hello"; } +>c : 42 +>42 : 42 +>d : "hello" +>'hello' : "hello" +>'a' : "a" + +let p2 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a.b'); +>p2 : { readonly c: 42; readonly d: "hello"; } +>getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a.b') : { readonly c: 42; readonly d: "hello"; } +>getProp : { (obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; (obj: T, path: `${P0}.${P1}`): T[P0][P1]; (obj: T, path: P0): T[P0]; (obj: object, path: string): unknown; } +>{ a: { b: {c: 42, d: 'hello' }}} as const : { readonly a: { readonly b: { readonly c: 42; readonly d: "hello"; }; }; } +>{ a: { b: {c: 42, d: 'hello' }}} : { readonly a: { readonly b: { readonly c: 42; readonly d: "hello"; }; }; } +>a : { readonly b: { readonly c: 42; readonly d: "hello"; }; } +>{ b: {c: 42, d: 'hello' }} : { readonly b: { readonly c: 42; readonly d: "hello"; }; } +>b : { readonly c: 42; readonly d: "hello"; } +>{c: 42, d: 'hello' } : { readonly c: 42; readonly d: "hello"; } +>c : 42 +>42 : 42 +>d : "hello" +>'hello' : "hello" +>'a.b' : "a.b" + +let p3 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a.b.d'); +>p3 : "hello" +>getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a.b.d') : "hello" +>getProp : { (obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; (obj: T, path: `${P0}.${P1}`): T[P0][P1]; (obj: T, path: P0): T[P0]; (obj: object, path: string): unknown; } +>{ a: { b: {c: 42, d: 'hello' }}} as const : { readonly a: { readonly b: { readonly c: 42; readonly d: "hello"; }; }; } +>{ a: { b: {c: 42, d: 'hello' }}} : { readonly a: { readonly b: { readonly c: 42; readonly d: "hello"; }; }; } +>a : { readonly b: { readonly c: 42; readonly d: "hello"; }; } +>{ b: {c: 42, d: 'hello' }} : { readonly b: { readonly c: 42; readonly d: "hello"; }; } +>b : { readonly c: 42; readonly d: "hello"; } +>{c: 42, d: 'hello' } : { readonly c: 42; readonly d: "hello"; } +>c : 42 +>42 : 42 +>d : "hello" +>'hello' : "hello" +>'a.b.d' : "a.b.d" + +type PropType = +>PropType : PropType + + string extends Path ? unknown : + Path extends keyof T ? T[Path] : + Path extends `${infer K}.${infer R}` ? K extends keyof T ? PropType : unknown : + unknown; + +declare function getPropValue(obj: T, path: P): PropType; +>getPropValue : (obj: T, path: P) => PropType +>obj : T +>path : P + +declare const s: string; +>s : string + +const obj = { a: { b: {c: 42, d: 'hello' }}}; +>obj : { a: { b: { c: number; d: string; }; }; } +>{ a: { b: {c: 42, d: 'hello' }}} : { a: { b: { c: number; d: string; }; }; } +>a : { b: { c: number; d: string; }; } +>{ b: {c: 42, d: 'hello' }} : { b: { c: number; d: string; }; } +>b : { c: number; d: string; } +>{c: 42, d: 'hello' } : { c: number; d: string; } +>c : number +>42 : 42 +>d : string +>'hello' : "hello" + +getPropValue(obj, 'a'); // { b: {c: number, d: string } } +>getPropValue(obj, 'a') : { b: { c: number; d: string; }; } +>getPropValue : (obj: T, path: P) => PropType +>obj : { a: { b: { c: number; d: string; }; }; } +>'a' : "a" + +getPropValue(obj, 'a.b'); // {c: number, d: string } +>getPropValue(obj, 'a.b') : { c: number; d: string; } +>getPropValue : (obj: T, path: P) => PropType +>obj : { a: { b: { c: number; d: string; }; }; } +>'a.b' : "a.b" + +getPropValue(obj, 'a.b.d'); // string +>getPropValue(obj, 'a.b.d') : string +>getPropValue : (obj: T, path: P) => PropType +>obj : { a: { b: { c: number; d: string; }; }; } +>'a.b.d' : "a.b.d" + +getPropValue(obj, 'a.b.x'); // unknown +>getPropValue(obj, 'a.b.x') : unknown +>getPropValue : (obj: T, path: P) => PropType +>obj : { a: { b: { c: number; d: string; }; }; } +>'a.b.x' : "a.b.x" + +getPropValue(obj, s); // unknown +>getPropValue(obj, s) : unknown +>getPropValue : (obj: T, path: P) => PropType +>obj : { a: { b: { c: number; d: string; }; }; } +>s : string + +// Infer type variables in template literals have string constraint + +type S1 = T extends `foo${infer U}bar` ? S2 : never; +>S1 : S1 + +type S2 = S; +>S2 : S + +// Batched single character inferences for lower recursion depth + +type Chars = +>Chars : Chars + + string extends S ? string[] : + S extends `${infer C0}${infer C1}${infer C2}${infer C3}${infer C4}${infer C5}${infer C6}${infer C7}${infer C8}${infer C9}${infer R}` ? [C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, ...Chars] : + S extends `${infer C}${infer R}` ? [C, ...Chars] : + S extends '' ? [] : + never; + +type L1 = Chars<'FooBarBazThisIsALongerString'>; // ['F', 'o', 'o', 'B', 'a', 'r', ...] +>L1 : ["F", "o", "o", "B", "a", "r", "B", "a", "z", "T", "h", "i", "s", "I", "s", "A", "L", "o", "n", "g", "e", "r", "S", "t", "r", "i", "n", "g"] + +// Cross product unions limited to 100,000 constituents + +type A = any; +>A : any + +type U1 = {a1:A} | {b1:A} | {c1:A} | {d1:A} | {e1:A} | {f1:A} | {g1:A} | {h1:A} | {i1:A} | {j1:A}; +>U1 : U1 +>a1 : any +>b1 : any +>c1 : any +>d1 : any +>e1 : any +>f1 : any +>g1 : any +>h1 : any +>i1 : any +>j1 : any + +type U2 = {a2:A} | {b2:A} | {c2:A} | {d2:A} | {e2:A} | {f2:A} | {g2:A} | {h2:A} | {i2:A} | {j2:A}; +>U2 : U2 +>a2 : any +>b2 : any +>c2 : any +>d2 : any +>e2 : any +>f2 : any +>g2 : any +>h2 : any +>i2 : any +>j2 : any + +type U3 = {a3:A} | {b3:A} | {c3:A} | {d3:A} | {e3:A} | {f3:A} | {g3:A} | {h3:A} | {i3:A} | {j3:A}; +>U3 : U3 +>a3 : any +>b3 : any +>c3 : any +>d3 : any +>e3 : any +>f3 : any +>g3 : any +>h3 : any +>i3 : any +>j3 : any + +type U4 = {a4:A} | {b4:A} | {c4:A} | {d4:A} | {e4:A} | {f4:A} | {g4:A} | {h4:A} | {i4:A} | {j4:A}; +>U4 : U4 +>a4 : any +>b4 : any +>c4 : any +>d4 : any +>e4 : any +>f4 : any +>g4 : any +>h4 : any +>i4 : any +>j4 : any + +type U5 = {a5:A} | {b5:A} | {c5:A} | {d5:A} | {e5:A} | {f5:A} | {g5:A} | {h5:A} | {i5:A} | {j5:A}; +>U5 : U5 +>a5 : any +>b5 : any +>c5 : any +>d5 : any +>e5 : any +>f5 : any +>g5 : any +>h5 : any +>i5 : any +>j5 : any + +type U100000 = U1 & U2 & U3 & U4 & U5; // Error +>U100000 : any + +type Digits = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; +>Digits : Digits + +type D100000 = `${Digits}${Digits}${Digits}${Digits}${Digits}`; // Error +>D100000 : any + +type TDigits = [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9]; +>TDigits : TDigits + +type T100000 = [...TDigits, ...TDigits, ...TDigits, ...TDigits, ...TDigits]; // Error +>T100000 : any + diff --git a/tests/baselines/reference/templateStringInFunctionParameterType.errors.txt b/tests/baselines/reference/templateStringInFunctionParameterType.errors.txt index 256d9dc1e9105..2ae9873ad9e72 100644 --- a/tests/baselines/reference/templateStringInFunctionParameterType.errors.txt +++ b/tests/baselines/reference/templateStringInFunctionParameterType.errors.txt @@ -1,20 +1,10 @@ -tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts(1,10): error TS2391: Function implementation is missing or not immediately following the declaration. -tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts(1,10): error TS2394: This overload signature is not compatible with its implementation signature. -tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts(1,12): error TS1138: Parameter declaration expected. -tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts(1,19): error TS1005: ';' expected. +tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts(1,12): error TS1003: Identifier expected. -==== tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts (4 errors) ==== +==== tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts (1 errors) ==== function f(`hello`); - ~ -!!! error TS2391: Function implementation is missing or not immediately following the declaration. - ~ -!!! error TS2394: This overload signature is not compatible with its implementation signature. -!!! related TS2750 tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts:3:10: The implementation signature is declared here. ~~~~~~~ -!!! error TS1138: Parameter declaration expected. - ~ -!!! error TS1005: ';' expected. +!!! error TS1003: Identifier expected. function f(x: string); function f(x: string) { return x; diff --git a/tests/baselines/reference/templateStringInFunctionParameterType.js b/tests/baselines/reference/templateStringInFunctionParameterType.js index a824a8ee91a96..2c2d364eb6fc1 100644 --- a/tests/baselines/reference/templateStringInFunctionParameterType.js +++ b/tests/baselines/reference/templateStringInFunctionParameterType.js @@ -6,9 +6,6 @@ function f(x: string) { } //// [templateStringInFunctionParameterType.js] -function f() { } -"hello"; -; function f(x) { return x; } diff --git a/tests/baselines/reference/templateStringInFunctionParameterType.symbols b/tests/baselines/reference/templateStringInFunctionParameterType.symbols index 91ce5f631f811..8f53b538adfbc 100644 --- a/tests/baselines/reference/templateStringInFunctionParameterType.symbols +++ b/tests/baselines/reference/templateStringInFunctionParameterType.symbols @@ -1,6 +1,7 @@ === tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts === function f(`hello`); >f : Symbol(f, Decl(templateStringInFunctionParameterType.ts, 0, 0), Decl(templateStringInFunctionParameterType.ts, 0, 20), Decl(templateStringInFunctionParameterType.ts, 1, 22)) +> : Symbol((Missing), Decl(templateStringInFunctionParameterType.ts, 0, 11)) function f(x: string); >f : Symbol(f, Decl(templateStringInFunctionParameterType.ts, 0, 0), Decl(templateStringInFunctionParameterType.ts, 0, 20), Decl(templateStringInFunctionParameterType.ts, 1, 22)) diff --git a/tests/baselines/reference/templateStringInFunctionParameterType.types b/tests/baselines/reference/templateStringInFunctionParameterType.types index 9b8f1cd5df1fe..e6b14dda5c72c 100644 --- a/tests/baselines/reference/templateStringInFunctionParameterType.types +++ b/tests/baselines/reference/templateStringInFunctionParameterType.types @@ -1,14 +1,14 @@ === tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts === function f(`hello`); ->f : { (): any; (x: string): any; } ->`hello` : "hello" +>f : { (: any): any; (x: string): any; } +> : any function f(x: string); ->f : { (): any; (x: string): any; } +>f : { (: any): any; (x: string): any; } >x : string function f(x: string) { ->f : { (): any; (x: string): any; } +>f : { (: any): any; (x: string): any; } >x : string return x; diff --git a/tests/baselines/reference/templateStringInFunctionParameterTypeES6.errors.txt b/tests/baselines/reference/templateStringInFunctionParameterTypeES6.errors.txt index feb068d49578a..1ca99ea6e2357 100644 --- a/tests/baselines/reference/templateStringInFunctionParameterTypeES6.errors.txt +++ b/tests/baselines/reference/templateStringInFunctionParameterTypeES6.errors.txt @@ -1,20 +1,10 @@ -tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts(1,10): error TS2391: Function implementation is missing or not immediately following the declaration. -tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts(1,10): error TS2394: This overload signature is not compatible with its implementation signature. -tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts(1,12): error TS1138: Parameter declaration expected. -tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts(1,19): error TS1005: ';' expected. +tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts(1,12): error TS1003: Identifier expected. -==== tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts (4 errors) ==== +==== tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts (1 errors) ==== function f(`hello`); - ~ -!!! error TS2391: Function implementation is missing or not immediately following the declaration. - ~ -!!! error TS2394: This overload signature is not compatible with its implementation signature. -!!! related TS2750 tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts:3:10: The implementation signature is declared here. ~~~~~~~ -!!! error TS1138: Parameter declaration expected. - ~ -!!! error TS1005: ';' expected. +!!! error TS1003: Identifier expected. function f(x: string); function f(x: string) { return x; diff --git a/tests/baselines/reference/templateStringInFunctionParameterTypeES6.js b/tests/baselines/reference/templateStringInFunctionParameterTypeES6.js index 41742f6757df0..0a1a88c104535 100644 --- a/tests/baselines/reference/templateStringInFunctionParameterTypeES6.js +++ b/tests/baselines/reference/templateStringInFunctionParameterTypeES6.js @@ -6,9 +6,6 @@ function f(x: string) { } //// [templateStringInFunctionParameterTypeES6.js] -function f() { } -`hello`; -; function f(x) { return x; } diff --git a/tests/baselines/reference/templateStringInFunctionParameterTypeES6.symbols b/tests/baselines/reference/templateStringInFunctionParameterTypeES6.symbols index aa2557259c263..1a3770457b9f9 100644 --- a/tests/baselines/reference/templateStringInFunctionParameterTypeES6.symbols +++ b/tests/baselines/reference/templateStringInFunctionParameterTypeES6.symbols @@ -1,6 +1,7 @@ === tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts === function f(`hello`); >f : Symbol(f, Decl(templateStringInFunctionParameterTypeES6.ts, 0, 0), Decl(templateStringInFunctionParameterTypeES6.ts, 0, 20), Decl(templateStringInFunctionParameterTypeES6.ts, 1, 22)) +> : Symbol((Missing), Decl(templateStringInFunctionParameterTypeES6.ts, 0, 11)) function f(x: string); >f : Symbol(f, Decl(templateStringInFunctionParameterTypeES6.ts, 0, 0), Decl(templateStringInFunctionParameterTypeES6.ts, 0, 20), Decl(templateStringInFunctionParameterTypeES6.ts, 1, 22)) diff --git a/tests/baselines/reference/templateStringInFunctionParameterTypeES6.types b/tests/baselines/reference/templateStringInFunctionParameterTypeES6.types index 6e79c161f8b98..516e5449071d0 100644 --- a/tests/baselines/reference/templateStringInFunctionParameterTypeES6.types +++ b/tests/baselines/reference/templateStringInFunctionParameterTypeES6.types @@ -1,14 +1,14 @@ === tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts === function f(`hello`); ->f : { (): any; (x: string): any; } ->`hello` : "hello" +>f : { (: any): any; (x: string): any; } +> : any function f(x: string); ->f : { (): any; (x: string): any; } +>f : { (: any): any; (x: string): any; } >x : string function f(x: string) { ->f : { (): any; (x: string): any; } +>f : { (: any): any; (x: string): any; } >x : string return x; diff --git a/tests/baselines/reference/typeAliases.types b/tests/baselines/reference/typeAliases.types index 6611e8357ec3f..f2804339e5892 100644 --- a/tests/baselines/reference/typeAliases.types +++ b/tests/baselines/reference/typeAliases.types @@ -72,13 +72,13 @@ var x7: T7; >x7 : C7 type T8 = string | boolean; ->T8 : string | boolean +>T8 : T8 var x8: string | boolean; ->x8 : string | boolean +>x8 : T8 var x8: T8; ->x8 : string | boolean +>x8 : T8 type T9 = () => string; >T9 : T9 diff --git a/tests/baselines/reference/unionWithIndexSignature.types b/tests/baselines/reference/unionWithIndexSignature.types index d80e8d01ca3c4..17554d4538a4e 100644 --- a/tests/baselines/reference/unionWithIndexSignature.types +++ b/tests/baselines/reference/unionWithIndexSignature.types @@ -28,10 +28,10 @@ export function foo(arr: T & (NumList | StrList)) { // Repro from #38102 export type TypedArray = Int32Array | Uint8Array; ->TypedArray : Int32Array | Uint8Array +>TypedArray : TypedArray export function isTypedArray(a: {}): a is Int32Array | Uint8Array { ->isTypedArray : (a: {}) => a is Int32Array | Uint8Array +>isTypedArray : (a: {}) => a is TypedArray >a : {} return a instanceof Int32Array || a instanceof Uint8Array; @@ -50,7 +50,7 @@ export function flatten(arr: T) { if (isTypedArray(arr)) { >isTypedArray(arr) : boolean ->isTypedArray : (a: {}) => a is Int32Array | Uint8Array +>isTypedArray : (a: {}) => a is TypedArray >arr : T arr[1]; diff --git a/tests/cases/conformance/types/literal/templateLiteralTypes1.ts b/tests/cases/conformance/types/literal/templateLiteralTypes1.ts new file mode 100644 index 0000000000000..55952d44bd6d8 --- /dev/null +++ b/tests/cases/conformance/types/literal/templateLiteralTypes1.ts @@ -0,0 +1,195 @@ +// @strict: true +// @declaration: true + +// Template types example from #12754 + +const createScopedActionType = (scope: S) => (type: T) => `${scope}/${type}` as `${S}/${T}`; +const createActionInMyScope = createScopedActionType("MyScope"); // (type: T) => `MyScope/${T}` +const MY_ACTION = createActionInMyScope("MY_ACTION"); // 'MyScope/MY_ACTION' + +// Union types are distributed over template types + +type EventName = `${S}Changed`; +type EN1 = EventName<'Foo' | 'Bar' | 'Baz'>; +type Loc = `${'top' | 'middle' | 'bottom'}-${'left' | 'center' | 'right'}`; + +// Primitive literal types can be spread into templates + +type ToString = `${T}`; +type TS1 = ToString<'abc' | 42 | true | -1234n>; + +// Casing modifiers + +type Cases = `${uppercase T} ${lowercase T} ${capitalize T} ${uncapitalize T}`; + +type TCA1 = Cases<'bar'>; // 'BAR bar Bar bar' +type TCA2 = Cases<'BAR'>; // 'BAR bar BAR bAR' + +// Assignability + +function test(name: `get${capitalize T}`) { + let s1: string = name; + let s2: 'getFoo' | 'getBar' = name; +} + +function fa1(x: T, y: { [P in keyof T]: T[P] }, z: { [P in keyof T & string as `p_${P}`]: T[P] }) { + y = x; + z = x; // Error +} + +function fa2(x: { [P in B as `p_${P}`]: T }, y: { [Q in A as `p_${Q}`]: U }) { + x = y; + y = x; // Error +} + +// String transformations using recursive conditional types + +type Join = + T extends [] ? '' : + T extends [unknown] ? `${T[0]}` : + T extends [unknown, ...infer U] ? `${T[0]}${D}${Join}` : + string; + +type TJ1 = Join<[1, 2, 3, 4], '.'> +type TJ2 = Join<['foo', 'bar', 'baz'], '-'>; +type TJ3 = Join<[], '.'> + +// Inference based on delimiters + +type MatchPair = S extends `[${infer A},${infer B}]` ? [A, B] : unknown; + +type T20 = MatchPair<'[1,2]'>; // ['1', '2'] +type T21 = MatchPair<'[foo,bar]'>; // ['foo', 'bar'] +type T22 = MatchPair<' [1,2]'>; // unknown +type T23 = MatchPair<'[123]'>; // unknown +type T24 = MatchPair<'[1,2,3,4]'>; // ['1', '2,3,4'] + +type SnakeToCamelCase = + S extends `${infer T}_${infer U}` ? `${lowercase T}${SnakeToPascalCase}` : + S extends `${infer T}` ? `${lowercase T}` : + SnakeToPascalCase; + +type SnakeToPascalCase = + string extends S ? string : + S extends `${infer T}_${infer U}` ? `${capitalize `${lowercase T}`}${SnakeToPascalCase}` : + S extends `${infer T}` ? `${capitalize `${lowercase T}`}` : + never; + +type RR0 = SnakeToPascalCase<'hello_world_foo'>; // 'HelloWorldFoo' +type RR1 = SnakeToPascalCase<'FOO_BAR_BAZ'>; // 'FooBarBaz' +type RR2 = SnakeToCamelCase<'hello_world_foo'>; // 'helloWorldFoo' +type RR3 = SnakeToCamelCase<'FOO_BAR_BAZ'>; // 'fooBarBaz' + +// Single character inference + +type FirstTwoAndRest = S extends `${infer A}${infer B}${infer R}` ? [`${A}${B}`, R] : unknown; + +type T25 = FirstTwoAndRest<'abcde'>; // ['ab', 'cde'] +type T26 = FirstTwoAndRest<'ab'>; // ['ab', ''] +type T27 = FirstTwoAndRest<'a'>; // unknown + +type Capitalize = S extends `${infer H}${infer T}` ? `${uppercase H}${T}` : S; +type Uncapitalize = S extends `${infer H}${infer T}` ? `${lowercase H}${T}` : S; + +type TC1 = Capitalize<'foo'>; // 'Foo' +type TC2 = Uncapitalize<'Foo'>; // 'foo' + +type HexDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' |'8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'; + +type HexColor = + S extends `#${infer R1}${infer R2}${infer G1}${infer G2}${infer B1}${infer B2}` ? + [R1, R2, G1, G2, B1, B2] extends [HexDigit, HexDigit, HexDigit, HexDigit, HexDigit, HexDigit] ? + S : + never : + never; + +type TH1 = HexColor<'#8080FF'>; // '#8080FF' +type TH2 = HexColor<'#80c0ff'>; // '#80c0ff' +type TH3 = HexColor<'#8080F'>; // never +type TH4 = HexColor<'#8080FFF'>; // never + +// Recursive inference + +type Trim = + S extends ` ${infer T}` ? Trim : + S extends `${infer T} ` ? Trim : + S; + +type TR1 = Trim<'xx '>; // 'xx' +type TR2 = Trim<' xx'>; // 'xx' +type TR3 = Trim<' xx '>; // 'xx' + +type Split = + string extends S ? string[] : + S extends '' ? [] : + S extends `${infer T}${D}${infer U}` ? [T, ...Split] : + [S]; + +type T40 = Split<'foo', '.'>; // ['foo'] +type T41 = Split<'foo.bar.baz', '.'>; // ['foo', 'bar', 'baz'] +type T42 = Split<'foo.bar', ''>; // ['f', 'o', 'o', '.', 'b', 'a', 'r'] +type T43 = Split; // string[] + +// Inference and property name paths + +declare function getProp(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; +declare function getProp(obj: T, path: `${P0}.${P1}`): T[P0][P1]; +declare function getProp(obj: T, path: P0): T[P0]; +declare function getProp(obj: object, path: string): unknown; + +let p1 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a'); +let p2 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a.b'); +let p3 = getProp({ a: { b: {c: 42, d: 'hello' }}} as const, 'a.b.d'); + +type PropType = + string extends Path ? unknown : + Path extends keyof T ? T[Path] : + Path extends `${infer K}.${infer R}` ? K extends keyof T ? PropType : unknown : + unknown; + +declare function getPropValue(obj: T, path: P): PropType; +declare const s: string; + +const obj = { a: { b: {c: 42, d: 'hello' }}}; + +getPropValue(obj, 'a'); // { b: {c: number, d: string } } +getPropValue(obj, 'a.b'); // {c: number, d: string } +getPropValue(obj, 'a.b.d'); // string +getPropValue(obj, 'a.b.x'); // unknown +getPropValue(obj, s); // unknown + +// Infer type variables in template literals have string constraint + +type S1 = T extends `foo${infer U}bar` ? S2 : never; +type S2 = S; + +// Batched single character inferences for lower recursion depth + +type Chars = + string extends S ? string[] : + S extends `${infer C0}${infer C1}${infer C2}${infer C3}${infer C4}${infer C5}${infer C6}${infer C7}${infer C8}${infer C9}${infer R}` ? [C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, ...Chars] : + S extends `${infer C}${infer R}` ? [C, ...Chars] : + S extends '' ? [] : + never; + +type L1 = Chars<'FooBarBazThisIsALongerString'>; // ['F', 'o', 'o', 'B', 'a', 'r', ...] + +// Cross product unions limited to 100,000 constituents + +type A = any; + +type U1 = {a1:A} | {b1:A} | {c1:A} | {d1:A} | {e1:A} | {f1:A} | {g1:A} | {h1:A} | {i1:A} | {j1:A}; +type U2 = {a2:A} | {b2:A} | {c2:A} | {d2:A} | {e2:A} | {f2:A} | {g2:A} | {h2:A} | {i2:A} | {j2:A}; +type U3 = {a3:A} | {b3:A} | {c3:A} | {d3:A} | {e3:A} | {f3:A} | {g3:A} | {h3:A} | {i3:A} | {j3:A}; +type U4 = {a4:A} | {b4:A} | {c4:A} | {d4:A} | {e4:A} | {f4:A} | {g4:A} | {h4:A} | {i4:A} | {j4:A}; +type U5 = {a5:A} | {b5:A} | {c5:A} | {d5:A} | {e5:A} | {f5:A} | {g5:A} | {h5:A} | {i5:A} | {j5:A}; + +type U100000 = U1 & U2 & U3 & U4 & U5; // Error + +type Digits = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + +type D100000 = `${Digits}${Digits}${Digits}${Digits}${Digits}`; // Error + +type TDigits = [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9]; + +type T100000 = [...TDigits, ...TDigits, ...TDigits, ...TDigits, ...TDigits]; // Error diff --git a/tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts b/tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts new file mode 100644 index 0000000000000..51f6bd720bf4b --- /dev/null +++ b/tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts @@ -0,0 +1,32 @@ +// @strict: true +// @declaration: true + +// Mapped type 'as N' clauses + +type Getters = { [P in keyof T & string as `get${capitalize P}`]: () => T[P] }; +type TG1 = Getters<{ foo: string, bar: number, baz: { z: boolean } }>; + +// Mapped type with 'as N' clause has no constraint on 'in T' clause + +type PropDef = { name: K, type: T }; + +type TypeFromDefs> = { [P in T as P['name']]: P['type'] }; + +type TP1 = TypeFromDefs<{ name: 'a', type: string } | { name: 'b', type: number } | { name: 'a', type: boolean }>; + +// No array or tuple type mapping when 'as N' clause present + +type TA1 = Getters; +type TA2 = Getters<[number, boolean]>; + +// Filtering using 'as N' clause + +type Methods = { [P in keyof T as T[P] extends Function ? P : never]: T[P] }; +type TM1 = Methods<{ foo(): number, bar(x: string): boolean, baz: string | number }>; + +// Mapping to multiple names using 'as N' clause + +type DoubleProp = { [P in keyof T & string as `${P}1` | `${P}2`]: T[P] } +type TD1 = DoubleProp<{ a: string, b: number }>; // { a1: string, a2: string, b1: number, b2: number } +type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2' +type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & string}2`