Template literal types and mapped type 'as' clauses (#40336)

* Initial implementation of string template types

* Accept new API baselines

* Accept new baselines

* Unified checking for large cross product union types

* Accept new baselines

* Ensure errors from union type resolution are reported

* Accept new baselines

* Compute constraints for string template types

* Support `as T` clause in mapped types

* Accept new API baselines

* Add missing semicolon

* Add checking of `as T` clauses

* Support casing modifiers in string template types

* Accept new baselines

* Bump keyword maximum length

* fix anders

* Revert "fix anders"

This reverts commit b3178d46184c068b7b83008ad98a52faac1e8a34.

* Properly handle 'as T' clause with keyof for mapped type

* Fix lint error

* Single character inferences and anchored end span matching

* Fewer array copy operations in template literal type resolution

* Handle cases where 'as T' maps multiple properties onto one

* Fix lint error

* Store key type instead of type mapper in MappedSymbol

* No constraint on `in T` type when `as N` clause present

* Rename from TemplateType to TemplateLiteralType

* Accept new API baselines

* Add tests

* Accept new baselines

* Address CR feedback

* Accept new API baselines

Co-authored-by: Erich Gamma <egamma@microsoft.com>
This commit is contained in:
Anders Hejlsberg 2020-09-09 17:23:22 -10:00 committed by GitHub
parent 96b0832cf6
commit 6f0c91c4cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 3474 additions and 583 deletions

View File

@ -698,6 +698,7 @@ namespace ts {
const intersectionTypes = new Map<string, Type>();
const literalTypes = new Map<string, LiteralType>();
const indexedAccessTypes = new Map<string, IndexedAccessType>();
const templateLiteralTypes = new Map<string, TemplateLiteralType>();
const substitutionTypes = new Map<string, SubstitutionType>();
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(<TypeParameter>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 = (<TemplateLiteralType>type).texts;
const casings = (<TemplateLiteralType>type).casings;
const types = (<TemplateLiteralType>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((<IndexedAccessType>type).objectType, context);
const indexTypeNode = typeToTypeNodeHelper((<IndexedAccessType>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((<IndexType>type).type);
return isGenericTupleType(t) ? getKnownKeysOfTupleType(t) : getIndexType(t);
@ -10373,7 +10386,7 @@ namespace ts {
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(sameMap((<UnionType>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(<MappedType>type.target || type);
const templateType = getTemplateTypeFromMappedType(<MappedType>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 = <MappedSymbol>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(<MappedType>symbol.mappedType.target || symbol.mappedType);
const propType = instantiateType(templateType, symbol.mapper);
const templateType = getTemplateTypeFromMappedType(<MappedType>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(<InstantiableType | UnionOrIntersectionType>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 = (<TemplateLiteralType>t).types;
const constraints = mapDefined(types, getBaseConstraint);
return constraints.length === types.length ? getTemplateLiteralType((<TemplateLiteralType>t).texts, (<TemplateLiteralType>t).casings, constraints) : stringType;
}
if (t.flags & TypeFlags.IndexedAccess) {
const baseObjectType = getBaseConstraint((<IndexedAccessType>t).objectType);
const baseIndexType = getBaseConstraint((<IndexedAccessType>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 && (<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 ? (<UnionType>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 ? (<UnionType>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((<IntersectionType>type).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) :
type.flags & TypeFlags.Intersection ? getUnionType(map((<IntersectionType>type).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) :
type.flags & TypeFlags.InstantiableNonPrimitive || isGenericTupleType(type) ? getIndexTypeForGenericType(<InstantiableType | UnionOrIntersectionType>type, stringsOnly) :
getObjectFlags(type) & ObjectFlags.Mapped ? filterType(getConstraintTypeFromMappedType(<MappedType>type), t => !(noIndexSignatures && t.flags & (TypeFlags.Any | TypeFlags.String))) :
getObjectFlags(type) & ObjectFlags.Mapped ? getIndexTypeForMappedType(<MappedType>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 ? (<StringLiteralType>type).value :
type.flags & TypeFlags.NumberLiteral ? "" + (<NumberLiteralType>type).value :
type.flags & TypeFlags.BigIntLiteral ? pseudoBigIntToString((<BigIntLiteralType>type).value) :
type.flags & TypeFlags.BooleanLiteral ? (<IntrinsicType>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 = <TemplateLiteralType>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 = <IndexedAccessType>createType(TypeFlags.IndexedAccess);
type.objectType = objectType;
@ -13624,7 +13750,7 @@ namespace ts {
}
return !!((<UnionOrIntersectionType>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(<ConditionalTypeNode>node);
case SyntaxKind.InferType:
return getTypeFromInferTypeNode(<InferTypeNode>node);
case SyntaxKind.TemplateLiteralType:
return getTypeFromTemplateTypeNode(<TemplateLiteralTypeNode>node);
case SyntaxKind.ImportType:
return getTypeFromImportTypeNode(<ImportTypeNode>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((<IndexType>type).type, mapper));
}
if (flags & TypeFlags.TemplateLiteral) {
return getTemplateLiteralType((<TemplateLiteralType>type).texts, (<TemplateLiteralType>type).casings, instantiateTypes((<TemplateLiteralType>type).types, mapper));
}
if (flags & TypeFlags.IndexedAccess) {
return getIndexedAccessType(instantiateType((<IndexedAccessType>type).objectType, mapper), instantiateType((<IndexedAccessType>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(<MappedType>source))) {
if (getObjectFlags(source) & ObjectFlags.Mapped && !(<MappedType>source).declaration.nameType && isRelatedTo(getIndexType(target), getConstraintTypeFromMappedType(<MappedType>source))) {
if (!(getMappedTypeModifiers(<MappedType>source) & MappedTypeModifiers.IncludeOptional)) {
const templateType = getTemplateTypeFromMappedType(<MappedType>source);
const indexedAccessType = getIndexedAccessType(target, getTypeParameterFromMappedType(<MappedType>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, <TemplateLiteralType>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(<StringLiteralType>source, target) :
source.flags & TypeFlags.TemplateLiteral && arraysEqual((<TemplateLiteralType>source).texts, target.texts) && arraysEqual((<TemplateLiteralType>source).casings, target.casings)? (<TemplateLiteralType>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 && (
(<TypeReference>source).target === (<TypeReference>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 && !(<MappedType>target).declaration.nameType) {
const constraintType = getConstraintTypeFromMappedType(<MappedType>target);
if (inferToMappedType(source, <MappedType>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 = <MappedType>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(<ConditionalTypeNode>node);
case SyntaxKind.InferType:
return checkInferType(<InferTypeNode>node);
case SyntaxKind.TemplateLiteralType:
return checkTemplateType(<TemplateLiteralTypeNode>node);
case SyntaxKind.ImportType:
return checkImportType(<ImportTypeNode>node);
case SyntaxKind.NamedTupleMember:

View File

@ -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",

View File

@ -1313,6 +1313,8 @@ namespace ts {
return emitConstructSignature(<ConstructSignatureDeclaration>node);
case SyntaxKind.IndexSignature:
return emitIndexSignature(<IndexSignatureDeclaration>node);
case SyntaxKind.TemplateLiteralTypeSpan:
return emitTemplateTypeSpan(<TemplateLiteralTypeSpan>node);
// Types
case SyntaxKind.TypePredicate:
@ -1357,6 +1359,8 @@ namespace ts {
return emitMappedType(<MappedTypeNode>node);
case SyntaxKind.LiteralType:
return emitLiteralType(<LiteralTypeNode>node);
case SyntaxKind.TemplateLiteralType:
return emitTemplateType(<TemplateLiteralTypeNode>node);
case SyntaxKind.ImportType:
return emitImportTypeNode(<ImportTypeNode>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");

View File

@ -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<TemplateLiteralTypeSpan>(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<TemplateLiteralTypeNode>(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<ImportTypeNode>(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<MappedTypeNode>(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;
}

View File

@ -206,6 +206,7 @@ namespace ts {
case SyntaxKind.MappedType:
return visitNode(cbNode, (<MappedTypeNode>node).readonlyToken) ||
visitNode(cbNode, (<MappedTypeNode>node).typeParameter) ||
visitNode(cbNode, (<MappedTypeNode>node).nameType) ||
visitNode(cbNode, (<MappedTypeNode>node).questionToken) ||
visitNode(cbNode, (<MappedTypeNode>node).type);
case SyntaxKind.LiteralType:
@ -424,6 +425,10 @@ namespace ts {
return visitNode(cbNode, (<TemplateExpression>node).head) || visitNodes(cbNode, cbNodes, (<TemplateExpression>node).templateSpans);
case SyntaxKind.TemplateSpan:
return visitNode(cbNode, (<TemplateSpan>node).expression) || visitNode(cbNode, (<TemplateSpan>node).literal);
case SyntaxKind.TemplateLiteralType:
return visitNode(cbNode, (<TemplateLiteralTypeNode>node).head) || visitNodes(cbNode, cbNodes, (<TemplateLiteralTypeNode>node).templateSpans);
case SyntaxKind.TemplateLiteralTypeSpan:
return visitNode(cbNode, (<TemplateLiteralTypeSpan>node).type) || visitNode(cbNode, (<TemplateLiteralTypeSpan>node).literal);
case SyntaxKind.ComputedPropertyName:
return visitNode(cbNode, (<ComputedPropertyName>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;

View File

@ -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);

View File

@ -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<TemplateLiteralTypeSpan>;
}
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<T> : Bar<T>', 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

View File

@ -565,6 +565,7 @@ namespace ts {
return factory.updateMappedTypeNode((<MappedTypeNode>node),
nodeVisitor((<MappedTypeNode>node).readonlyToken, tokenVisitor, isToken),
nodeVisitor((<MappedTypeNode>node).typeParameter, visitor, isTypeParameterDeclaration),
nodeVisitor((<MappedTypeNode>node).nameType, visitor, isTypeNode),
nodeVisitor((<MappedTypeNode>node).questionToken, tokenVisitor, isToken),
nodeVisitor((<MappedTypeNode>node).type, visitor, isTypeNode));

View File

@ -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));
}
}

View File

@ -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([

View File

@ -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<TemplateLiteralTypeSpan>;
}
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<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, 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<TKind extends KeywordTypeSyntaxKind>(kind: TKind): KeywordTypeNode<TKind>;
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. */

View File

@ -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<TemplateLiteralTypeSpan>;
}
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<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, 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<TKind extends KeywordTypeSyntaxKind>(kind: TKind): KeywordTypeNode<TKind>;
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. */

View File

@ -15,7 +15,7 @@ declare function Func<Values = object, ExtraProps = {}>(
>Func : <Values = object, ExtraProps = {}>(x: (string extends "validate" | "initialValues" | keyof ExtraProps ? Readonly<FormikConfig<Values> & ExtraProps> : Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validate" | "initialValues" | Exclude<keyof ExtraProps, "validateOnChange">> & Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>)) => void
x: (string extends "validate" | "initialValues" | keyof ExtraProps
>x : string extends keyof ExtraProps | "validate" | "initialValues" ? Readonly<FormikConfig<Values> & ExtraProps> : Pick<Readonly<FormikConfig<Values> & ExtraProps>, Exclude<keyof ExtraProps, "validateOnChange"> | "validate" | "initialValues"> & Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>
>x : string extends "validate" | "initialValues" | keyof ExtraProps ? Readonly<FormikConfig<Values> & ExtraProps> : Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validate" | "initialValues" | Exclude<keyof ExtraProps, "validateOnChange">> & Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>
? Readonly<FormikConfig<Values> & ExtraProps>
: Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validate" | "initialValues" | Exclude<keyof ExtraProps, "validateOnChange">>
@ -24,7 +24,7 @@ declare function Func<Values = object, ExtraProps = {}>(
Func({
>Func({ initialValues: { foo: "" }, validate: props => { props.foo; }}) : void
>Func : <Values = object, ExtraProps = {}>(x: string extends keyof ExtraProps | "validate" | "initialValues" ? Readonly<FormikConfig<Values> & ExtraProps> : Pick<Readonly<FormikConfig<Values> & ExtraProps>, Exclude<keyof ExtraProps, "validateOnChange"> | "validate" | "initialValues"> & Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>) => void
>Func : <Values = object, ExtraProps = {}>(x: string extends "validate" | "initialValues" | keyof ExtraProps ? Readonly<FormikConfig<Values> & ExtraProps> : Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validate" | "initialValues" | Exclude<keyof ExtraProps, "validateOnChange">> & Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>) => void
>{ initialValues: { foo: "" }, validate: props => { props.foo; }} : { initialValues: { foo: string; }; validate: (props: { foo: string; }) => void; }
initialValues: {

View File

@ -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 : <T, K extends keyof T>(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 : <T, K extends keyof T>(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<Shape>) {
>component.getProperty : <K extends "name" | "width" | "height" | "visible">(key: K) => Shape[K]
>component : Component<Shape>
>getProperty : <K extends "name" | "width" | "height" | "visible">(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<Shape>) {
>component.setProperty : <K extends "name" | "width" | "height" | "visible">(key: K, value: Shape[K]) => void
>component : Component<Shape>
>setProperty : <K extends "name" | "width" | "height" | "visible">(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<K extends keyof Shape>(key: K) {
}
function f32<K extends "width" | "height">(key: K) {
>f32 : <K extends "width" | "height">(key: K) => Shape[K]
>f32 : <K extends WIDTH_OR_HEIGHT>(key: K) => Shape[K]
>key : K
const shape: Shape = { name: "foo", width: 5, height: 10, visible: true };

View File

@ -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

View File

@ -0,0 +1,84 @@
//// [mappedTypeAsClauses.ts]
// Mapped type 'as N' clauses
type Getters<T> = { [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<K extends keyof any, T> = { name: K, type: T };
type TypeFromDefs<T extends PropDef<keyof any, any>> = { [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<string[]>;
type TA2 = Getters<[number, boolean]>;
// Filtering using 'as N' clause
type Methods<T> = { [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<T> = { [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<U> = keyof DoubleProp<U>; // `${keyof U & string}1` | `${keyof U & string}2`
//// [mappedTypeAsClauses.js]
"use strict";
// Mapped type 'as N' clauses
//// [mappedTypeAsClauses.d.ts]
declare type Getters<T> = {
[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<K extends keyof any, T> = {
name: K;
type: T;
};
declare type TypeFromDefs<T extends PropDef<keyof any, any>> = {
[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<string[]>;
declare type TA2 = Getters<[number, boolean]>;
declare type Methods<T> = {
[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<T> = {
[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<U> = keyof DoubleProp<U>;

View File

@ -0,0 +1,110 @@
=== tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts ===
// Mapped type 'as N' clauses
type Getters<T> = { [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<K extends keyof any, T> = { 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<T extends PropDef<keyof any, any>> = { [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<string[]>;
>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<T> = { [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<T> = { [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<U> = keyof DoubleProp<U>; // `${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))

View File

@ -0,0 +1,68 @@
=== tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts ===
// Mapped type 'as N' clauses
type Getters<T> = { [P in keyof T & string as `get${capitalize P}`]: () => T[P] };
>Getters : Getters<T>
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<K extends keyof any, T> = { name: K, type: T };
>PropDef : PropDef<K, T>
>name : K
>type : T
type TypeFromDefs<T extends PropDef<keyof any, any>> = { [P in T as P['name']]: P['type'] };
>TypeFromDefs : TypeFromDefs<T>
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<string[]>;
>TA1 : Getters<string[]>
type TA2 = Getters<[number, boolean]>;
>TA2 : Getters<[number, boolean]>
// Filtering using 'as N' clause
type Methods<T> = { [P in keyof T as T[P] extends Function ? P : never]: T[P] };
>Methods : Methods<T>
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<T> = { [P in keyof T & string as `${P}1` | `${P}2`]: T[P] }
>DoubleProp : DoubleProp<T>
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<U> = keyof DoubleProp<U>; // `${keyof U & string}1` | `${keyof U & string}2`
>TD3 : `${keyof U & string}1` | `${keyof U & string}2`

View File

@ -66,7 +66,7 @@ type B = { b: string };
>b : string
type T40 = Boxified<A | A[] | ReadonlyArray<A> | [A, B] | string | string[]>;
>T40 : string | Box<string>[] | Boxified<A> | readonly Box<A>[] | Box<A>[] | [Box<A>, Box<B>]
>T40 : string | Box<string>[] | Boxified<A> | readonly Box<A>[] | [Box<A>, Box<B>] | Box<A>[]
type ReadWrite<T> = { -readonly [P in keyof T] : T[P] };
>ReadWrite : ReadWrite<T>

View File

@ -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' }

View File

@ -132,7 +132,7 @@ function test<T extends IFoo>() {
// 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; }

View File

@ -2,7 +2,7 @@
// Repro from #38236
type Type = string | object;
>Type : string | object
>Type : Type
class SyncableObject {
>SyncableObject : SyncableObject

View File

@ -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

View File

@ -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

View File

@ -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 = <S extends string>(scope: S) => <T extends string>(type: T) => `${scope}/${type}` as `${S}/${T}`;
const createActionInMyScope = createScopedActionType("MyScope"); // <T extends string>(type: T) => `MyScope/${T}`
const MY_ACTION = createActionInMyScope("MY_ACTION"); // 'MyScope/MY_ACTION'
// Union types are distributed over template types
type EventName<S extends string> = `${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 extends string | number | boolean | bigint> = `${T}`;
type TS1 = ToString<'abc' | 42 | true | -1234n>;
// Casing modifiers
type Cases<T extends string> = `${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<T extends 'foo' | 'bar'>(name: `get${capitalize T}`) {
let s1: string = name;
let s2: 'getFoo' | 'getBar' = name;
}
function fa1<T>(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<T, U extends T, A extends string, B extends A>(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 (string | number | boolean | bigint)[], D extends string> =
T extends [] ? '' :
T extends [unknown] ? `${T[0]}` :
T extends [unknown, ...infer U] ? `${T[0]}${D}${Join<U, D>}` :
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 string> = 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 string> =
S extends `${infer T}_${infer U}` ? `${lowercase T}${SnakeToPascalCase<U>}` :
S extends `${infer T}` ? `${lowercase T}` :
SnakeToPascalCase<S>;
type SnakeToPascalCase<S extends string> =
string extends S ? string :
S extends `${infer T}_${infer U}` ? `${capitalize `${lowercase T}`}${SnakeToPascalCase<U>}` :
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 string> = 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 string> = S extends `${infer H}${infer T}` ? `${uppercase H}${T}` : S;
type Uncapitalize<S extends string> = 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 string> =
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 string> =
S extends ` ${infer T}` ? Trim<T> :
S extends `${infer T} ` ? Trim<T> :
S;
type TR1 = Trim<'xx '>; // 'xx'
type TR2 = Trim<' xx'>; // 'xx'
type TR3 = Trim<' xx '>; // 'xx'
type Split<S extends string, D extends string> =
string extends S ? string[] :
S extends '' ? [] :
S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] :
[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<any, '.'>; // string[]
// Inference and property name paths
declare function getProp<T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2];
declare function getProp<T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(obj: T, path: `${P0}.${P1}`): T[P0][P1];
declare function getProp<T, P0 extends keyof T & string>(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<T, Path extends string> =
string extends Path ? unknown :
Path extends keyof T ? T[Path] :
Path extends `${infer K}.${infer R}` ? K extends keyof T ? PropType<T[K], R> : unknown :
unknown;
declare function getPropValue<T, P extends string>(obj: T, path: P): PropType<T, P>;
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> = T extends `foo${infer U}bar` ? S2<U> : never;
type S2<S extends string> = S;
// Batched single character inferences for lower recursion depth
type Chars<S extends string> =
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<R>] :
S extends `${infer C}${infer R}` ? [C, ...Chars<R>] :
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.

View File

@ -0,0 +1,437 @@
//// [templateLiteralTypes1.ts]
// Template types example from #12754
const createScopedActionType = <S extends string>(scope: S) => <T extends string>(type: T) => `${scope}/${type}` as `${S}/${T}`;
const createActionInMyScope = createScopedActionType("MyScope"); // <T extends string>(type: T) => `MyScope/${T}`
const MY_ACTION = createActionInMyScope("MY_ACTION"); // 'MyScope/MY_ACTION'
// Union types are distributed over template types
type EventName<S extends string> = `${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 extends string | number | boolean | bigint> = `${T}`;
type TS1 = ToString<'abc' | 42 | true | -1234n>;
// Casing modifiers
type Cases<T extends string> = `${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<T extends 'foo' | 'bar'>(name: `get${capitalize T}`) {
let s1: string = name;
let s2: 'getFoo' | 'getBar' = name;
}
function fa1<T>(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<T, U extends T, A extends string, B extends A>(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 (string | number | boolean | bigint)[], D extends string> =
T extends [] ? '' :
T extends [unknown] ? `${T[0]}` :
T extends [unknown, ...infer U] ? `${T[0]}${D}${Join<U, D>}` :
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 string> = 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 string> =
S extends `${infer T}_${infer U}` ? `${lowercase T}${SnakeToPascalCase<U>}` :
S extends `${infer T}` ? `${lowercase T}` :
SnakeToPascalCase<S>;
type SnakeToPascalCase<S extends string> =
string extends S ? string :
S extends `${infer T}_${infer U}` ? `${capitalize `${lowercase T}`}${SnakeToPascalCase<U>}` :
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 string> = 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 string> = S extends `${infer H}${infer T}` ? `${uppercase H}${T}` : S;
type Uncapitalize<S extends string> = 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 string> =
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 string> =
S extends ` ${infer T}` ? Trim<T> :
S extends `${infer T} ` ? Trim<T> :
S;
type TR1 = Trim<'xx '>; // 'xx'
type TR2 = Trim<' xx'>; // 'xx'
type TR3 = Trim<' xx '>; // 'xx'
type Split<S extends string, D extends string> =
string extends S ? string[] :
S extends '' ? [] :
S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] :
[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<any, '.'>; // string[]
// Inference and property name paths
declare function getProp<T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2];
declare function getProp<T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(obj: T, path: `${P0}.${P1}`): T[P0][P1];
declare function getProp<T, P0 extends keyof T & string>(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<T, Path extends string> =
string extends Path ? unknown :
Path extends keyof T ? T[Path] :
Path extends `${infer K}.${infer R}` ? K extends keyof T ? PropType<T[K], R> : unknown :
unknown;
declare function getPropValue<T, P extends string>(obj: T, path: P): PropType<T, P>;
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> = T extends `foo${infer U}bar` ? S2<U> : never;
type S2<S extends string> = S;
// Batched single character inferences for lower recursion depth
type Chars<S extends string> =
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<R>] :
S extends `${infer C}${infer R}` ? [C, ...Chars<R>] :
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"); // <T extends string>(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: <S extends string>(scope: S) => <T extends string>(type: T) => `${S}/${T}`;
declare const createActionInMyScope: <T extends string>(type: T) => `MyScope/${T}`;
declare const MY_ACTION: "MyScope/MY_ACTION";
declare type EventName<S extends string> = `${S}Changed`;
declare type EN1 = EventName<'Foo' | 'Bar' | 'Baz'>;
declare type Loc = `${'top' | 'middle' | 'bottom'}-${'left' | 'center' | 'right'}`;
declare type ToString<T extends string | number | boolean | bigint> = `${T}`;
declare type TS1 = ToString<'abc' | 42 | true | -1234n>;
declare type Cases<T extends string> = `${uppercase T} ${lowercase T} ${capitalize T} ${uncapitalize T}`;
declare type TCA1 = Cases<'bar'>;
declare type TCA2 = Cases<'BAR'>;
declare function test<T extends 'foo' | 'bar'>(name: `get${capitalize T}`): void;
declare function fa1<T>(x: T, y: {
[P in keyof T]: T[P];
}, z: {
[P in keyof T & string as `p_${P}`]: T[P];
}): void;
declare function fa2<T, U extends T, A extends string, B extends A>(x: {
[P in B as `p_${P}`]: T;
}, y: {
[Q in A as `p_${Q}`]: U;
}): void;
declare type Join<T extends (string | number | boolean | bigint)[], D extends string> = T extends [] ? '' : T extends [unknown] ? `${T[0]}` : T extends [unknown, ...infer U] ? `${T[0]}${D}${Join<U, D>}` : 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 string> = 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 string> = S extends `${infer T}_${infer U}` ? `${lowercase T}${SnakeToPascalCase<U>}` : S extends `${infer T}` ? `${lowercase T}` : SnakeToPascalCase<S>;
declare type SnakeToPascalCase<S extends string> = string extends S ? string : S extends `${infer T}_${infer U}` ? `${capitalize `${lowercase T}`}${SnakeToPascalCase<U>}` : 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 string> = 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 string> = S extends `${infer H}${infer T}` ? `${uppercase H}${T}` : S;
declare type Uncapitalize<S extends string> = 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 string> = 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 string> = S extends ` ${infer T}` ? Trim<T> : S extends `${infer T} ` ? Trim<T> : S;
declare type TR1 = Trim<'xx '>;
declare type TR2 = Trim<' xx'>;
declare type TR3 = Trim<' xx '>;
declare type Split<S extends string, D extends string> = string extends S ? string[] : S extends '' ? [] : S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] : [
S
];
declare type T40 = Split<'foo', '.'>;
declare type T41 = Split<'foo.bar.baz', '.'>;
declare type T42 = Split<'foo.bar', ''>;
declare type T43 = Split<any, '.'>;
declare function getProp<T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2];
declare function getProp<T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(obj: T, path: `${P0}.${P1}`): T[P0][P1];
declare function getProp<T, P0 extends keyof T & string>(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<T, Path extends string> = string extends Path ? unknown : Path extends keyof T ? T[Path] : Path extends `${infer K}.${infer R}` ? K extends keyof T ? PropType<T[K], R> : unknown : unknown;
declare function getPropValue<T, P extends string>(obj: T, path: P): PropType<T, P>;
declare const s: string;
declare const obj: {
a: {
b: {
c: number;
d: string;
};
};
};
declare type S1<T> = T extends `foo${infer U}bar` ? S2<U> : never;
declare type S2<S extends string> = S;
declare type Chars<S extends string> = 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<R>] : S extends `${infer C}${infer R}` ? [C, ...Chars<R>] : 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];

View File

@ -0,0 +1,813 @@
=== tests/cases/conformance/types/literal/templateLiteralTypes1.ts ===
// Template types example from #12754
const createScopedActionType = <S extends string>(scope: S) => <T extends string>(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"); // <T extends string>(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 extends string> = `${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 extends string | number | boolean | bigint> = `${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<T extends string> = `${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<T extends 'foo' | 'bar'>(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<T>(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<T, U extends T, A extends string, B extends A>(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<T extends (string | number | boolean | bigint)[], D extends string> =
>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<U, D>}` :
>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 string> = 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<S extends string> =
>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<U>}` :
>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<S>;
>SnakeToPascalCase : Symbol(SnakeToPascalCase, Decl(templateLiteralTypes1.ts, 66, 25))
>S : Symbol(S, Decl(templateLiteralTypes1.ts, 63, 22))
type SnakeToPascalCase<S extends string> =
>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<U>}` :
>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 string> = 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 string> = 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 string> = 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<S extends string> =
>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<S extends string> =
>Trim : Symbol(Trim, Decl(templateLiteralTypes1.ts, 105, 32))
>S : Symbol(S, Decl(templateLiteralTypes1.ts, 109, 10))
S extends ` ${infer T}` ? Trim<T> :
>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<T> :
>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<S extends string, D extends string> =
>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<U, D>] :
>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<any, '.'>; // 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<T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(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<T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(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<T, P0 extends keyof T & string>(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<T, Path extends string> =
>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<T[K], R> : 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<T, P extends string>(obj: T, path: P): PropType<T, P>;
>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> = T extends `foo${infer U}bar` ? S2<U> : 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 extends string> = 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<S extends string> =
>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<R>] :
>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<R>] :
>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))

View File

@ -0,0 +1,496 @@
=== tests/cases/conformance/types/literal/templateLiteralTypes1.ts ===
// Template types example from #12754
const createScopedActionType = <S extends string>(scope: S) => <T extends string>(type: T) => `${scope}/${type}` as `${S}/${T}`;
>createScopedActionType : <S extends string>(scope: S) => <T extends string>(type: T) => `${S}/${T}`
><S extends string>(scope: S) => <T extends string>(type: T) => `${scope}/${type}` as `${S}/${T}` : <S extends string>(scope: S) => <T extends string>(type: T) => `${S}/${T}`
>scope : S
><T extends string>(type: T) => `${scope}/${type}` as `${S}/${T}` : <T extends string>(type: T) => `${S}/${T}`
>type : T
>`${scope}/${type}` as `${S}/${T}` : `${S}/${T}`
>`${scope}/${type}` : string
>scope : S
>type : T
const createActionInMyScope = createScopedActionType("MyScope"); // <T extends string>(type: T) => `MyScope/${T}`
>createActionInMyScope : <T extends string>(type: T) => `MyScope/${T}`
>createScopedActionType("MyScope") : <T extends string>(type: T) => `MyScope/${T}`
>createScopedActionType : <S extends string>(scope: S) => <T extends string>(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 : <T extends string>(type: T) => `MyScope/${T}`
>"MY_ACTION" : "MY_ACTION"
// Union types are distributed over template types
type EventName<S extends string> = `${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 extends string | number | boolean | bigint> = `${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<T extends string> = `${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<T extends 'foo' | 'bar'>(name: `get${capitalize T}`) {
>test : <T extends "bar" | "foo">(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<T>(x: T, y: { [P in keyof T]: T[P] }, z: { [P in keyof T & string as `p_${P}`]: T[P] }) {
>fa1 : <T>(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<T, U extends T, A extends string, B extends A>(x: { [P in B as `p_${P}`]: T }, y: { [Q in A as `p_${Q}`]: U }) {
>fa2 : <T, U extends T, A extends string, B extends A>(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<T extends (string | number | boolean | bigint)[], D extends string> =
>Join : Join<T, D>
T extends [] ? '' :
T extends [unknown] ? `${T[0]}` :
T extends [unknown, ...infer U] ? `${T[0]}${D}${Join<U, D>}` :
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 string> = S extends `[${infer A},${infer B}]` ? [A, B] : unknown;
>MatchPair : MatchPair<S>
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<S extends string> =
>SnakeToCamelCase : SnakeToCamelCase<S>
S extends `${infer T}_${infer U}` ? `${lowercase T}${SnakeToPascalCase<U>}` :
S extends `${infer T}` ? `${lowercase T}` :
SnakeToPascalCase<S>;
type SnakeToPascalCase<S extends string> =
>SnakeToPascalCase : SnakeToPascalCase<S>
string extends S ? string :
S extends `${infer T}_${infer U}` ? `${capitalize `${lowercase T}`}${SnakeToPascalCase<U>}` :
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 string> = S extends `${infer A}${infer B}${infer R}` ? [`${A}${B}`, R] : unknown;
>FirstTwoAndRest : FirstTwoAndRest<S>
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 string> = S extends `${infer H}${infer T}` ? `${uppercase H}${T}` : S;
>Capitalize : Capitalize<S>
type Uncapitalize<S extends string> = S extends `${infer H}${infer T}` ? `${lowercase H}${T}` : S;
>Uncapitalize : Uncapitalize<S>
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<S extends string> =
>HexColor : HexColor<S>
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<S extends string> =
>Trim : Trim<S>
S extends ` ${infer T}` ? Trim<T> :
S extends `${infer T} ` ? Trim<T> :
S;
type TR1 = Trim<'xx '>; // 'xx'
>TR1 : "xx"
type TR2 = Trim<' xx'>; // 'xx'
>TR2 : "xx"
type TR3 = Trim<' xx '>; // 'xx'
>TR3 : "xx"
type Split<S extends string, D extends string> =
>Split : Split<S, D>
string extends S ? string[] :
S extends '' ? [] :
S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] :
[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<any, '.'>; // string[]
>T43 : string[]
// Inference and property name paths
declare function getProp<T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2];
>getProp : { <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(obj: T, path: `${P0}.${P1}`): T[P0][P1]; <T, P0 extends keyof T & string>(obj: T, path: P0): T[P0]; (obj: object, path: string): unknown; }
>obj : T
>path : `${P0}.${P1}.${P2}`
declare function getProp<T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(obj: T, path: `${P0}.${P1}`): T[P0][P1];
>getProp : { <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(obj: T, path: `${P0}.${P1}`): T[P0][P1]; <T, P0 extends keyof T & string>(obj: T, path: P0): T[P0]; (obj: object, path: string): unknown; }
>obj : T
>path : `${P0}.${P1}`
declare function getProp<T, P0 extends keyof T & string>(obj: T, path: P0): T[P0];
>getProp : { <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(obj: T, path: `${P0}.${P1}`): T[P0][P1]; <T, P0 extends keyof T & string>(obj: T, path: P0): T[P0]; (obj: object, path: string): unknown; }
>obj : T
>path : P0
declare function getProp(obj: object, path: string): unknown;
>getProp : { <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(obj: T, path: `${P0}.${P1}`): T[P0][P1]; <T, P0 extends keyof T & string>(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 : { <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(obj: T, path: `${P0}.${P1}`): T[P0][P1]; <T, P0 extends keyof T & string>(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 : { <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(obj: T, path: `${P0}.${P1}`): T[P0][P1]; <T, P0 extends keyof T & string>(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 : { <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2]; <T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(obj: T, path: `${P0}.${P1}`): T[P0][P1]; <T, P0 extends keyof T & string>(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<T, Path extends string> =
>PropType : PropType<T, Path>
string extends Path ? unknown :
Path extends keyof T ? T[Path] :
Path extends `${infer K}.${infer R}` ? K extends keyof T ? PropType<T[K], R> : unknown :
unknown;
declare function getPropValue<T, P extends string>(obj: T, path: P): PropType<T, P>;
>getPropValue : <T, P extends string>(obj: T, path: P) => PropType<T, P>
>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 : <T, P extends string>(obj: T, path: P) => PropType<T, P>
>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 : <T, P extends string>(obj: T, path: P) => PropType<T, P>
>obj : { a: { b: { c: number; d: string; }; }; }
>'a.b' : "a.b"
getPropValue(obj, 'a.b.d'); // string
>getPropValue(obj, 'a.b.d') : string
>getPropValue : <T, P extends string>(obj: T, path: P) => PropType<T, P>
>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 : <T, P extends string>(obj: T, path: P) => PropType<T, P>
>obj : { a: { b: { c: number; d: string; }; }; }
>'a.b.x' : "a.b.x"
getPropValue(obj, s); // unknown
>getPropValue(obj, s) : unknown
>getPropValue : <T, P extends string>(obj: T, path: P) => PropType<T, P>
>obj : { a: { b: { c: number; d: string; }; }; }
>s : string
// Infer type variables in template literals have string constraint
type S1<T> = T extends `foo${infer U}bar` ? S2<U> : never;
>S1 : S1<T>
type S2<S extends string> = S;
>S2 : S
// Batched single character inferences for lower recursion depth
type Chars<S extends string> =
>Chars : Chars<S>
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<R>] :
S extends `${infer C}${infer R}` ? [C, ...Chars<R>] :
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

View File

@ -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;

View File

@ -6,9 +6,6 @@ function f(x: string) {
}
//// [templateStringInFunctionParameterType.js]
function f() { }
"hello";
;
function f(x) {
return x;
}

View File

@ -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))

View File

@ -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;

View File

@ -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;

View File

@ -6,9 +6,6 @@ function f(x: string) {
}
//// [templateStringInFunctionParameterTypeES6.js]
function f() { }
`hello`;
;
function f(x) {
return x;
}

View File

@ -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))

View File

@ -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;

View File

@ -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

View File

@ -28,10 +28,10 @@ export function foo<T extends NumList | StrList>(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<T extends number|TypedArray>(arr: T) {
if (isTypedArray(arr)) {
>isTypedArray(arr) : boolean
>isTypedArray : (a: {}) => a is Int32Array | Uint8Array
>isTypedArray : (a: {}) => a is TypedArray
>arr : T
arr[1];

View File

@ -0,0 +1,195 @@
// @strict: true
// @declaration: true
// Template types example from #12754
const createScopedActionType = <S extends string>(scope: S) => <T extends string>(type: T) => `${scope}/${type}` as `${S}/${T}`;
const createActionInMyScope = createScopedActionType("MyScope"); // <T extends string>(type: T) => `MyScope/${T}`
const MY_ACTION = createActionInMyScope("MY_ACTION"); // 'MyScope/MY_ACTION'
// Union types are distributed over template types
type EventName<S extends string> = `${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 extends string | number | boolean | bigint> = `${T}`;
type TS1 = ToString<'abc' | 42 | true | -1234n>;
// Casing modifiers
type Cases<T extends string> = `${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<T extends 'foo' | 'bar'>(name: `get${capitalize T}`) {
let s1: string = name;
let s2: 'getFoo' | 'getBar' = name;
}
function fa1<T>(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<T, U extends T, A extends string, B extends A>(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 (string | number | boolean | bigint)[], D extends string> =
T extends [] ? '' :
T extends [unknown] ? `${T[0]}` :
T extends [unknown, ...infer U] ? `${T[0]}${D}${Join<U, D>}` :
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 string> = 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 string> =
S extends `${infer T}_${infer U}` ? `${lowercase T}${SnakeToPascalCase<U>}` :
S extends `${infer T}` ? `${lowercase T}` :
SnakeToPascalCase<S>;
type SnakeToPascalCase<S extends string> =
string extends S ? string :
S extends `${infer T}_${infer U}` ? `${capitalize `${lowercase T}`}${SnakeToPascalCase<U>}` :
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 string> = 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 string> = S extends `${infer H}${infer T}` ? `${uppercase H}${T}` : S;
type Uncapitalize<S extends string> = 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 string> =
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 string> =
S extends ` ${infer T}` ? Trim<T> :
S extends `${infer T} ` ? Trim<T> :
S;
type TR1 = Trim<'xx '>; // 'xx'
type TR2 = Trim<' xx'>; // 'xx'
type TR3 = Trim<' xx '>; // 'xx'
type Split<S extends string, D extends string> =
string extends S ? string[] :
S extends '' ? [] :
S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] :
[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<any, '.'>; // string[]
// Inference and property name paths
declare function getProp<T, P0 extends keyof T & string, P1 extends keyof T[P0] & string, P2 extends keyof T[P0][P1] & string>(obj: T, path: `${P0}.${P1}.${P2}`): T[P0][P1][P2];
declare function getProp<T, P0 extends keyof T & string, P1 extends keyof T[P0] & string>(obj: T, path: `${P0}.${P1}`): T[P0][P1];
declare function getProp<T, P0 extends keyof T & string>(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<T, Path extends string> =
string extends Path ? unknown :
Path extends keyof T ? T[Path] :
Path extends `${infer K}.${infer R}` ? K extends keyof T ? PropType<T[K], R> : unknown :
unknown;
declare function getPropValue<T, P extends string>(obj: T, path: P): PropType<T, P>;
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> = T extends `foo${infer U}bar` ? S2<U> : never;
type S2<S extends string> = S;
// Batched single character inferences for lower recursion depth
type Chars<S extends string> =
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<R>] :
S extends `${infer C}${infer R}` ? [C, ...Chars<R>] :
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

View File

@ -0,0 +1,32 @@
// @strict: true
// @declaration: true
// Mapped type 'as N' clauses
type Getters<T> = { [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<K extends keyof any, T> = { name: K, type: T };
type TypeFromDefs<T extends PropDef<keyof any, any>> = { [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<string[]>;
type TA2 = Getters<[number, boolean]>;
// Filtering using 'as N' clause
type Methods<T> = { [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<T> = { [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<U> = keyof DoubleProp<U>; // `${keyof U & string}1` | `${keyof U & string}2`