Merge branch 'main' into timestamps

This commit is contained in:
Sheetal Nandi
2022-06-01 10:24:33 -07:00
124 changed files with 8460 additions and 435 deletions
+17 -17
View File
@@ -234,7 +234,7 @@
"normalize-path": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
"integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
"integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
"dev": true,
"requires": {
"remove-trailing-separator": "^1.0.1"
@@ -638,9 +638,9 @@
"dev": true
},
"@types/node": {
"version": "17.0.35",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz",
"integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==",
"version": "17.0.38",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.38.tgz",
"integrity": "sha512-5jY9RhV7c0Z4Jy09G+NIDTsCZ5G0L5n+Z+p+Y7t5VJHM30bgwzSjVtlcBxqAj+6L/swIlvtOSzr8rBk/aNyV2g==",
"dev": true
},
"@types/node-fetch": {
@@ -1964,7 +1964,7 @@
"detect-newline": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz",
"integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=",
"integrity": "sha512-CwffZFvlJffUg9zZA0uqrjQayUTC8ob94pnr5sFwaVv3IOmkfUHcWH+jXaQK3askE51Cqe8/9Ql/0uXNwqZ8Zg==",
"dev": true
},
"diff": {
@@ -2600,7 +2600,7 @@
"event-emitter": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
"integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
"integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
"dev": true,
"requires": {
"d": "1",
@@ -3130,7 +3130,7 @@
"get-func-name": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
"integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==",
"dev": true
},
"get-intrinsic": {
@@ -3390,7 +3390,7 @@
"gulp-concat": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz",
"integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=",
"integrity": "sha512-a2scActrQrDBpBbR3WUZGyGS1JEPLg5PZJdIa7/Bi3GuKAmPYDK6SFhy/NZq5R8KsKKFvtfR0fakbUCcKGCCjg==",
"dev": true,
"requires": {
"concat-with-sourcemaps": "^1.0.0",
@@ -3401,7 +3401,7 @@
"gulp-insert": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/gulp-insert/-/gulp-insert-0.5.0.tgz",
"integrity": "sha1-MjE/E+SiPPWsylzl8MCAkjx3hgI=",
"integrity": "sha512-SDKCWmjomAo0N0Bzj9qEKIfURORJR/72p6AbDBIK9yKZw794ROTrQHliBem+NJzS2GsTWSm8dGWJ5L7KtjnMRA==",
"dev": true,
"requires": {
"readable-stream": "^1.0.26-4",
@@ -3411,7 +3411,7 @@
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
"dev": true
},
"readable-stream": {
@@ -4006,7 +4006,7 @@
"kew": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz",
"integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=",
"integrity": "sha512-IG6nm0+QtAMdXt9KvbgbGdvY50RSrw+U4sGZg+KlrSKPJEwVE5JVoI3d7RWfSMdBQneRheeAOj3lIjX5VL/9RQ==",
"dev": true
},
"kind-of": {
@@ -4138,7 +4138,7 @@
"lru-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz",
"integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=",
"integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==",
"dev": true,
"requires": {
"es5-ext": "~0.10.2"
@@ -4705,7 +4705,7 @@
"mocha-fivemat-progress-reporter": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/mocha-fivemat-progress-reporter/-/mocha-fivemat-progress-reporter-0.1.0.tgz",
"integrity": "sha1-zK/w4ckc9Vf+d+B535lUuRt0d1Y=",
"integrity": "sha512-nCf6dmCEHObJ8BBrcjW+UHYvVtHEL+FliYR/Mfc/v7dKenNmBQ0ZSuvlICgsyQy9Tt581ldvh+SReS4qp4LrQw==",
"dev": true
},
"ms": {
@@ -4834,7 +4834,7 @@
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true
},
"object-copy": {
@@ -5192,7 +5192,7 @@
"extend-shallow": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz",
"integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=",
"integrity": "sha512-L7AGmkO6jhDkEBBGWlLtftA80Xq8DipnrRPr0pyi7GQLXkaq9JYA4xF4z6qnadIC6euiTDKco0cGSU9muw+WTw==",
"dev": true,
"requires": {
"kind-of": "^1.1.0"
@@ -5201,7 +5201,7 @@
"kind-of": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
"integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
"integrity": "sha512-aUH6ElPnMGon2/YkxRIigV32MOpTVcoXQ1Oo8aYn40s+sJ3j+0gFZsT8HKDcxNy7Fi9zuquWtGaGAahOdv5p/g==",
"dev": true
}
}
@@ -5960,7 +5960,7 @@
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
"dev": true
},
"readable-stream": {
+308 -165
View File
@@ -74,7 +74,7 @@ namespace ts {
TypeofNEString = 1 << 8, // typeof x !== "string"
TypeofNENumber = 1 << 9, // typeof x !== "number"
TypeofNEBigInt = 1 << 10, // typeof x !== "bigint"
TypeofNEBoolean = 1 << 11, // typeof x !== "boolean"
TypeofNEBoolean = 1 << 11, // typeof x !== "boolean"
TypeofNESymbol = 1 << 12, // typeof x !== "symbol"
TypeofNEObject = 1 << 13, // typeof x !== "object"
TypeofNEFunction = 1 << 14, // typeof x !== "function"
@@ -87,7 +87,10 @@ namespace ts {
NEUndefinedOrNull = 1 << 21, // x != undefined / x != null
Truthy = 1 << 22, // x
Falsy = 1 << 23, // !x
All = (1 << 24) - 1,
IsUndefined = 1 << 24, // Exactly undefined
IsNull = 1 << 25, // Exactly null
IsUndefinedOrNull = IsUndefined | IsNull,
All = (1 << 27) - 1,
// The following members encode facts about particular kinds of types for use in the getTypeFacts function.
// The presence of a particular fact means that the given test is true for some (and possibly all) values
// of that kind of type.
@@ -129,11 +132,13 @@ namespace ts {
ObjectFacts = ObjectStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy,
FunctionStrictFacts = TypeofEQFunction | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy,
FunctionFacts = FunctionStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy,
UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy,
NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy,
EmptyObjectStrictFacts = All & ~(EQUndefined | EQNull | EQUndefinedOrNull),
VoidFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy,
UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy | IsUndefined,
NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy | IsNull,
EmptyObjectStrictFacts = All & ~(EQUndefined | EQNull | EQUndefinedOrNull | IsUndefinedOrNull),
EmptyObjectFacts = All & ~IsUndefinedOrNull,
UnknownFacts = All & ~IsUndefinedOrNull,
AllTypeofNE = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | NEUndefined,
EmptyObjectFacts = All,
// Masks
OrFactsMask = TypeofEQFunction | TypeofNEObject,
AndFactsMask = All & ~OrFactsMask,
@@ -848,6 +853,8 @@ namespace ts {
emptyTypeLiteralSymbol.members = createSymbolTable();
const emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, emptyArray);
const unknownUnionType = strictNullChecks ? getUnionType([undefinedType, nullType, createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray)]) : unknownType;
const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray) as ObjectType as GenericType;
emptyGenericType.instantiations = new Map<string, TypeReference>();
@@ -2476,7 +2483,12 @@ namespace ts {
function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean {
if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) {
if (isPrimitiveTypeName(name)) {
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name));
if (isExtendedByInterface(errorLocation)) {
error(errorLocation, Diagnostics.An_interface_cannot_extend_a_primitive_type_like_0_an_interface_can_only_extend_named_types_and_classes, unescapeLeadingUnderscores(name));
}
else {
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name));
}
return true;
}
const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false));
@@ -2497,6 +2509,17 @@ namespace ts {
return false;
}
function isExtendedByInterface(node: Node): boolean {
const grandparent = node.parent.parent;
const parentOfGrandparent = grandparent.parent;
if(grandparent && parentOfGrandparent){
const isExtending = isHeritageClause(grandparent) && grandparent.token === SyntaxKind.ExtendsKeyword;
const isInterface = isInterfaceDeclaration(parentOfGrandparent);
return isExtending && isInterface;
}
return false;
}
function maybeMappedType(node: Node, symbol: Symbol) {
const container = findAncestor(node.parent, n =>
isComputedPropertyName(n) || isPropertySignature(n) ? false : isTypeLiteralNode(n) || "quit") as TypeLiteralNode | undefined;
@@ -5620,7 +5643,7 @@ namespace ts {
anyType : getNonMissingTypeOfSymbol(propertySymbol);
const saveEnclosingDeclaration = context.enclosingDeclaration;
context.enclosingDeclaration = undefined;
if (context.tracker.trackSymbol && getCheckFlags(propertySymbol) & CheckFlags.Late && isLateBoundName(propertySymbol.escapedName)) {
if (context.tracker.trackSymbol && isLateBoundName(propertySymbol.escapedName)) {
if (propertySymbol.declarations) {
const decl = first(propertySymbol.declarations);
if (hasLateBindableName(decl)) {
@@ -7556,7 +7579,7 @@ namespace ts {
...!length(baseTypes) ? [] : [factory.createHeritageClause(SyntaxKind.ExtendsKeyword, map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))],
...!length(implementsExpressions) ? [] : [factory.createHeritageClause(SyntaxKind.ImplementsKeyword, implementsExpressions)]
];
const symbolProps = getNonInterhitedProperties(classType, baseTypes, getPropertiesOfType(classType));
const symbolProps = getNonInheritedProperties(classType, baseTypes, getPropertiesOfType(classType));
const publicSymbolProps = filter(symbolProps, s => {
// `valueDeclaration` could be undefined if inherited from
// a union/intersection base type, but inherited properties
@@ -8885,7 +8908,7 @@ namespace ts {
if (getEffectiveTypeAnnotationNode(walkUpBindingElementsAndPatterns(declaration))) {
// In strict null checking mode, if a default value of a non-undefined type is specified, remove
// undefined from the final type.
return strictNullChecks && !(getFalsyFlags(checkDeclarationInitializer(declaration, CheckMode.Normal)) & TypeFlags.Undefined) ? getNonUndefinedType(type) : type;
return strictNullChecks && !(getTypeFacts(checkDeclarationInitializer(declaration, CheckMode.Normal)) & TypeFacts.IsUndefined) ? getNonUndefinedType(type) : type;
}
return widenTypeInferredFromInitializer(declaration, getUnionType([getNonUndefinedType(type), checkDeclarationInitializer(declaration, CheckMode.Normal)], UnionReduction.Subtype));
}
@@ -12058,7 +12081,7 @@ namespace ts {
}
}
}
else if (t.flags & TypeFlags.DisjointDomains) {
else if (t.flags & TypeFlags.DisjointDomains || isEmptyAnonymousObjectType(t)) {
hasDisjointDomainType = true;
}
}
@@ -12069,7 +12092,7 @@ namespace ts {
// We add any types belong to one of the disjoint domains because they might cause the final
// intersection operation to reduce the union constraints.
for (const t of types) {
if (t.flags & TypeFlags.DisjointDomains) {
if (t.flags & TypeFlags.DisjointDomains || isEmptyAnonymousObjectType(t)) {
constraints = append(constraints, t);
}
}
@@ -12285,7 +12308,7 @@ namespace ts {
let objectType;
return !!(type.flags & TypeFlags.IndexedAccess && getObjectFlags(objectType = (type as IndexedAccessType).objectType) & ObjectFlags.Mapped &&
!isGenericMappedType(objectType) && isGenericIndexType((type as IndexedAccessType).indexType) &&
!(objectType as MappedType).declaration.questionToken && !(objectType as MappedType).declaration.nameType);
!(getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.ExcludeOptional) && !(objectType as MappedType).declaration.nameType);
}
/**
@@ -14826,7 +14849,7 @@ namespace ts {
return includes;
}
function removeRedundantPrimitiveTypes(types: Type[], includes: TypeFlags) {
function removeRedundantSupertypes(types: Type[], includes: TypeFlags) {
let i = types.length;
while (i > 0) {
i--;
@@ -14835,7 +14858,9 @@ namespace ts {
t.flags & TypeFlags.String && includes & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ||
t.flags & TypeFlags.Number && includes & TypeFlags.NumberLiteral ||
t.flags & TypeFlags.BigInt && includes & TypeFlags.BigIntLiteral ||
t.flags & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol;
t.flags & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol ||
t.flags & TypeFlags.Void && includes & TypeFlags.Undefined ||
isEmptyAnonymousObjectType(t) && includes & TypeFlags.DefinitelyNonNullable;
if (remove) {
orderedRemoveItemAt(types, i);
}
@@ -14959,7 +14984,7 @@ namespace ts {
// a type alias of the form "type List<T> = T & { next: List<T> }" cannot be reduced during its declaration.
// Also, unlike union types, the order of the constituent types is preserved in order that overload resolution
// for intersections of types with signatures can be deterministic.
function getIntersectionType(types: readonly Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
function getIntersectionType(types: readonly Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], noSupertypeReduction?: boolean): Type {
const typeMembershipMap: ESMap<string, Type> = new Map();
const includes = addTypesToIntersection(typeMembershipMap, 0, types);
const typeSet: Type[] = arrayFrom(typeMembershipMap.values());
@@ -14996,11 +15021,10 @@ namespace ts {
if (includes & TypeFlags.String && includes & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ||
includes & TypeFlags.Number && includes & TypeFlags.NumberLiteral ||
includes & TypeFlags.BigInt && includes & TypeFlags.BigIntLiteral ||
includes & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol) {
removeRedundantPrimitiveTypes(typeSet, includes);
}
if (includes & TypeFlags.IncludesEmptyObject && includes & TypeFlags.Object) {
orderedRemoveItemAt(typeSet, findIndex(typeSet, isEmptyAnonymousObjectType));
includes & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol ||
includes & TypeFlags.Void && includes & TypeFlags.Undefined ||
includes & TypeFlags.IncludesEmptyObject && includes & TypeFlags.DefinitelyNonNullable) {
if (!noSupertypeReduction) removeRedundantSupertypes(typeSet, includes);
}
if (includes & TypeFlags.IncludesMissingType) {
typeSet[typeSet.indexOf(undefinedType)] = missingType;
@@ -15039,8 +15063,9 @@ namespace ts {
}
const constituents = getCrossProductIntersections(typeSet);
// We attach a denormalized origin type when at least one constituent of the cross-product union is an
// intersection (i.e. when the intersection didn't just reduce one or more unions to smaller unions).
const origin = some(constituents, t => !!(t.flags & TypeFlags.Intersection)) ? createOriginUnionOrIntersectionType(TypeFlags.Intersection, typeSet) : undefined;
// intersection (i.e. when the intersection didn't just reduce one or more unions to smaller unions) and
// the denormalized origin has fewer constituents than the union itself.
const origin = some(constituents, t => !!(t.flags & TypeFlags.Intersection)) && getConstituentCountOfTypes(constituents) > getConstituentCountOfTypes(typeSet) ? createOriginUnionOrIntersectionType(TypeFlags.Intersection, typeSet) : undefined;
result = getUnionType(constituents, UnionReduction.Literal, aliasSymbol, aliasTypeArguments, origin);
}
}
@@ -15086,12 +15111,23 @@ namespace ts {
return intersections;
}
function getConstituentCount(type: Type): number {
return !(type.flags & TypeFlags.UnionOrIntersection) || type.aliasSymbol ? 1 :
type.flags & TypeFlags.Union && (type as UnionType).origin ? getConstituentCount((type as UnionType).origin!) :
getConstituentCountOfTypes((type as UnionOrIntersectionType).types);
}
function getConstituentCountOfTypes(types: Type[]): number {
return reduceLeft(types, (n, t) => n + getConstituentCount(t), 0);
}
function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
const aliasSymbol = getAliasSymbolForTypeNode(node);
links.resolvedType = getIntersectionType(map(node.types, getTypeFromTypeNode),
aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol));
const types = map(node.types, getTypeFromTypeNode);
const noSupertypeReduction = types.length === 2 && !!(types[0].flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) && types[1] === emptyTypeLiteralType;
links.resolvedType = getIntersectionType(types, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol), noSupertypeReduction);
}
return links.resolvedType;
}
@@ -17981,7 +18017,7 @@ namespace ts {
const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType));
const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType));
const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) &&
(getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable);
(getTypeFacts(sourceType) & TypeFacts.IsUndefinedOrNull) === (getTypeFacts(targetType) & TypeFacts.IsUndefinedOrNull);
let related = callbacks ?
compareSignaturesRelated(targetSig, sourceSig, (checkMode & SignatureCheckMode.StrictArity) | (strictVariance ? SignatureCheckMode.StrictCallback : SignatureCheckMode.BivariantCallback), reportErrors, errorReporter, incompatibleErrorReporter, compareTypes, reportUnreliableMarkers) :
!(checkMode & SignatureCheckMode.Callback) && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors);
@@ -18116,6 +18152,18 @@ namespace ts {
type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral && getMembersOfSymbol(type.symbol).size === 0));
}
function isUnknownLikeUnionType(type: Type) {
if (strictNullChecks && type.flags & TypeFlags.Union) {
if (!((type as UnionType).objectFlags & ObjectFlags.IsUnknownLikeUnionComputed)) {
const types = (type as UnionType).types;
(type as UnionType).objectFlags |= ObjectFlags.IsUnknownLikeUnionComputed | (types.length >= 3 && types[0].flags & TypeFlags.Undefined &&
types[1].flags & TypeFlags.Null && some(types, isEmptyAnonymousObjectType) ? ObjectFlags.IsUnknownLikeUnion : 0);
}
return !!((type as UnionType).objectFlags & ObjectFlags.IsUnknownLikeUnion);
}
return false;
}
function isStringIndexSignatureOnlyType(type: Type): boolean {
return type.flags & TypeFlags.Object && !isGenericMappedType(type) && getPropertiesOfType(type).length === 0 && getIndexInfosOfType(type).length === 1 && !!getIndexInfoOfType(type, stringType) ||
type.flags & TypeFlags.UnionOrIntersection && every((type as UnionOrIntersectionType).types, isStringIndexSignatureOnlyType) ||
@@ -18183,7 +18231,7 @@ namespace ts {
// Since unions and intersections may reduce to `never`, we exclude them here.
if (s & TypeFlags.Undefined && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & (TypeFlags.Undefined | TypeFlags.Void))) return true;
if (s & TypeFlags.Null && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & TypeFlags.Null)) return true;
if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive) return true;
if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive && !(relation === strictSubtypeRelation && isEmptyAnonymousObjectType(source))) return true;
if (relation === assignableRelation || relation === comparableRelation) {
if (s & TypeFlags.Any) return true;
// Type number or any numeric literal type is assignable to any numeric enum type or any
@@ -18191,6 +18239,8 @@ namespace ts {
// bit-flag enum types sometimes look like literal enum types with numeric literal values.
if (s & (TypeFlags.Number | TypeFlags.NumberLiteral) && !(s & TypeFlags.EnumLiteral) && (
t & TypeFlags.Enum || relation === assignableRelation && t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral)) return true;
// Anything is assignable to a union containing undefined, null, and {}
if (isUnknownLikeUnionType(target)) return true;
}
return false;
}
@@ -18233,16 +18283,28 @@ namespace ts {
function getNormalizedType(type: Type, writing: boolean): Type {
while (true) {
let t = isFreshLiteralType(type) ? (type as FreshableType).regularType :
getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference).node ? createTypeReference((type as TypeReference).target, getTypeArguments(type as TypeReference)) :
type.flags & TypeFlags.UnionOrIntersection ? getReducedType(type) :
const t = isFreshLiteralType(type) ? (type as FreshableType).regularType :
getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).node ? createTypeReference((type as TypeReference).target, getTypeArguments(type as TypeReference)) : getSingleBaseForNonAugmentingSubtype(type) || type :
type.flags & TypeFlags.UnionOrIntersection ? getNormalizedUnionOrIntersectionType(type as UnionOrIntersectionType, writing) :
type.flags & TypeFlags.Substitution ? writing ? (type as SubstitutionType).baseType : (type as SubstitutionType).substitute :
type.flags & TypeFlags.Simplifiable ? getSimplifiedType(type, writing) :
type;
t = getSingleBaseForNonAugmentingSubtype(t) || t;
if (t === type) break;
if (t === type) return t;
type = t;
}
}
function getNormalizedUnionOrIntersectionType(type: UnionOrIntersectionType, writing: boolean) {
const reduced = getReducedType(type);
if (reduced !== type) {
return reduced;
}
if (type.flags & TypeFlags.Intersection) {
const normalizedTypes = sameMap(type.types, t => getNormalizedType(t, writing));
if (normalizedTypes !== type.types) {
return getIntersectionType(normalizedTypes);
}
}
return type;
}
@@ -18772,6 +18834,9 @@ namespace ts {
return;
}
reportRelationError(headMessage, source, target);
if (strictNullChecks && source.flags & TypeFlags.TypeVariable && source.symbol?.declarations?.[0] && !getConstraintOfType(source as TypeVariable) && isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive))) {
associateRelatedInfo(createDiagnosticForNode(source.symbol.declarations[0], Diagnostics.This_type_parameter_probably_needs_an_extends_object_constraint));
}
}
function traceUnionsOrIntersectionsTooLarge(source: Type, target: Type): void {
@@ -19576,13 +19641,6 @@ namespace ts {
// IndexedAccess comparisons are handled above in the `targetFlags & TypeFlage.IndexedAccess` branch
if (!(sourceFlags & TypeFlags.IndexedAccess && targetFlags & TypeFlags.IndexedAccess)) {
const constraint = getConstraintOfType(source as TypeVariable) || unknownType;
if (!getConstraintOfType(source as TypeVariable) || (sourceFlags & TypeFlags.TypeParameter && constraint.flags & TypeFlags.Any)) {
// A type variable with no constraint is not related to the non-primitive object type.
if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive), RecursionFlags.Both)) {
resetErrorInfo(saveErrorInfo);
return result;
}
}
// hi-speed no-this-instantiation check (less accurate, but avoids costly `this`-instantiation when the constraint will suffice), see #28231 for report on why this is needed
if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) {
resetErrorInfo(saveErrorInfo);
@@ -21106,9 +21164,11 @@ namespace ts {
return getSupertypeOrUnion(types);
}
const primaryTypes = filter(types, t => !(t.flags & TypeFlags.Nullable));
return primaryTypes.length ?
getNullableType(getSupertypeOrUnion(primaryTypes), getFalsyFlagsOfTypes(types) & TypeFlags.Nullable) :
getUnionType(types, UnionReduction.Subtype);
if (primaryTypes.length) {
const supertypeOrUnion = getSupertypeOrUnion(primaryTypes);
return primaryTypes === types ? supertypeOrUnion : getUnionType([supertypeOrUnion, ...filter(types, t => !!(t.flags & TypeFlags.Nullable))]);
}
return getUnionType(types, UnionReduction.Subtype);
}
// Return the leftmost type for which no type to the right is a subtype.
@@ -21325,30 +21385,8 @@ namespace ts {
return value.base10Value === "0";
}
function getFalsyFlagsOfTypes(types: Type[]): TypeFlags {
let result: TypeFlags = 0;
for (const t of types) {
result |= getFalsyFlags(t);
}
return result;
}
// Returns the String, Number, Boolean, StringLiteral, NumberLiteral, BooleanLiteral, Void, Undefined, or Null
// flags for the string, number, boolean, "", 0, false, void, undefined, or null types respectively. Returns
// no flags for all other types (including non-falsy literal types).
function getFalsyFlags(type: Type): TypeFlags {
return type.flags & TypeFlags.Union ? getFalsyFlagsOfTypes((type as UnionType).types) :
type.flags & TypeFlags.StringLiteral ? (type as StringLiteralType).value === "" ? TypeFlags.StringLiteral : 0 :
type.flags & TypeFlags.NumberLiteral ? (type as NumberLiteralType).value === 0 ? TypeFlags.NumberLiteral : 0 :
type.flags & TypeFlags.BigIntLiteral ? isZeroBigInt(type as BigIntLiteralType) ? TypeFlags.BigIntLiteral : 0 :
type.flags & TypeFlags.BooleanLiteral ? (type === falseType || type === regularFalseType) ? TypeFlags.BooleanLiteral : 0 :
type.flags & TypeFlags.PossiblyFalsy;
}
function removeDefinitelyFalsyTypes(type: Type): Type {
return getFalsyFlags(type) & TypeFlags.DefinitelyFalsy ?
filterType(type, t => !(getFalsyFlags(t) & TypeFlags.DefinitelyFalsy)) :
type;
return filterType(type, t => !!(getTypeFacts(t) & TypeFacts.Truthy));
}
function extractDefinitelyFalsyTypes(type: Type): Type {
@@ -21387,21 +21425,16 @@ namespace ts {
}
function getGlobalNonNullableTypeInstantiation(type: Type) {
// First reduce away any constituents that are assignable to 'undefined' or 'null'. This not only eliminates
// 'undefined' and 'null', but also higher-order types such as a type parameter 'U extends undefined | null'
// that isn't eliminated by a NonNullable<T> instantiation.
const reducedType = getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
if (!deferredGlobalNonNullableTypeAlias) {
deferredGlobalNonNullableTypeAlias = getGlobalSymbol("NonNullable" as __String, SymbolFlags.TypeAlias, /*diagnostic*/ undefined) || unknownSymbol;
}
// If the NonNullable<T> type is available, return an instantiation. Otherwise just return the reduced type.
return deferredGlobalNonNullableTypeAlias !== unknownSymbol ?
getTypeAliasInstantiation(deferredGlobalNonNullableTypeAlias, [reducedType]) :
reducedType;
getTypeAliasInstantiation(deferredGlobalNonNullableTypeAlias, [type]) :
getIntersectionType([type, emptyObjectType]);
}
function getNonNullableType(type: Type): Type {
return strictNullChecks ? getGlobalNonNullableTypeInstantiation(type) : type;
return strictNullChecks ? getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
}
function addOptionalTypeMarker(type: Type) {
@@ -22112,13 +22145,40 @@ namespace ts {
sourceEnd.slice(sourceEnd.length - endLen) !== targetEnd.slice(targetEnd.length - endLen);
}
function isValidBigIntString(s: string): boolean {
/**
* Tests whether the provided string can be parsed as a number.
* @param s The string to test.
* @param roundTripOnly Indicates the resulting number matches the input when converted back to a string.
*/
function isValidNumberString(s: string, roundTripOnly: boolean): boolean {
if (s === "") return false;
const n = +s;
return isFinite(n) && (!roundTripOnly || "" + n === s);
}
/**
* @param text a valid bigint string excluding a trailing `n`, but including a possible prefix `-`. Use `isValidBigIntString(text, roundTripOnly)` before calling this function.
*/
function parseBigIntLiteralType(text: string) {
const negative = text.startsWith("-");
const base10Value = parsePseudoBigInt(`${negative ? text.slice(1) : text}n`);
return getBigIntLiteralType({ negative, base10Value });
}
/**
* Tests whether the provided string can be parsed as a bigint.
* @param s The string to test.
* @param roundTripOnly Indicates the resulting bigint matches the input when converted back to a string.
*/
function isValidBigIntString(s: string, roundTripOnly: boolean): boolean {
if (s === "") return false;
const scanner = createScanner(ScriptTarget.ESNext, /*skipTrivia*/ false);
let success = true;
scanner.setOnError(() => success = false);
scanner.setText(s + "n");
let result = scanner.scan();
if (result === SyntaxKind.MinusToken) {
const negative = result === SyntaxKind.MinusToken;
if (negative) {
result = scanner.scan();
}
const flags = scanner.getTokenFlags();
@@ -22127,7 +22187,8 @@ namespace ts {
// * a bigint can be scanned, and that when it is scanned, it is
// * the full length of the input string (so the scanner is one character beyond the augmented input length)
// * it does not contain a numeric seperator (the `BigInt` constructor does not accept a numeric seperator in its input)
return success && result === SyntaxKind.BigIntLiteral && scanner.getTextPos() === (s.length + 1) && !(flags & TokenFlags.ContainsSeparator);
return success && result === SyntaxKind.BigIntLiteral && scanner.getTextPos() === (s.length + 1) && !(flags & TokenFlags.ContainsSeparator)
&& (!roundTripOnly || s === pseudoBigIntToString({ negative, base10Value: parsePseudoBigInt(scanner.getTokenValue()) }));
}
function isValidTypeForTemplateLiteralPlaceholder(source: Type, target: Type): boolean {
@@ -22136,8 +22197,8 @@ namespace ts {
}
if (source.flags & TypeFlags.StringLiteral) {
const value = (source as StringLiteralType).value;
return !!(target.flags & TypeFlags.Number && value !== "" && isFinite(+value) ||
target.flags & TypeFlags.BigInt && value !== "" && isValidBigIntString(value) ||
return !!(target.flags & TypeFlags.Number && isValidNumberString(value, /*roundTripOnly*/ false) ||
target.flags & TypeFlags.BigInt && isValidBigIntString(value, /*roundTripOnly*/ false) ||
target.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && value === (target as IntrinsicType).intrinsicName);
}
if (source.flags & TypeFlags.TemplateLiteral) {
@@ -22715,7 +22776,60 @@ namespace ts {
// succeed. That would be a pointless and confusing outcome.
if (matches || every(target.texts, s => s.length === 0)) {
for (let i = 0; i < types.length; i++) {
inferFromTypes(matches ? matches[i] : neverType, types[i]);
const source = matches ? matches[i] : neverType;
const target = types[i];
// If we are inferring from a string literal type to a type variable whose constraint includes one of the
// allowed template literal placeholder types, infer from a literal type corresponding to the constraint.
if (source.flags & TypeFlags.StringLiteral && target.flags & TypeFlags.TypeVariable) {
const inferenceContext = getInferenceInfoForType(target);
const constraint = inferenceContext ? getBaseConstraintOfType(inferenceContext.typeParameter) : undefined;
if (constraint && !isTypeAny(constraint)) {
const constraintTypes = constraint.flags & TypeFlags.Union ? (constraint as UnionType).types : [constraint];
let allTypeFlags: TypeFlags = reduceLeft(constraintTypes, (flags, t) => flags | t.flags, 0 as TypeFlags);
// If the constraint contains `string`, we don't need to look for a more preferred type
if (!(allTypeFlags & TypeFlags.String)) {
const str = (source as StringLiteralType).value;
// If the type contains `number` or a number literal and the string isn't a valid number, exclude numbers
if (allTypeFlags & TypeFlags.NumberLike && !isValidNumberString(str, /*roundTripOnly*/ true)) {
allTypeFlags &= ~TypeFlags.NumberLike;
}
// If the type contains `bigint` or a bigint literal and the string isn't a valid bigint, exclude bigints
if (allTypeFlags & TypeFlags.BigIntLike && !isValidBigIntString(str, /*roundTripOnly*/ true)) {
allTypeFlags &= ~TypeFlags.BigIntLike;
}
// for each type in the constraint, find the highest priority matching type
const matchingType = reduceLeft(constraintTypes, (left, right) =>
!(right.flags & allTypeFlags) ? left :
left.flags & TypeFlags.String ? left : right.flags & TypeFlags.String ? source :
left.flags & TypeFlags.TemplateLiteral ? left : right.flags & TypeFlags.TemplateLiteral && isTypeMatchedByTemplateLiteralType(source, right as TemplateLiteralType) ? source :
left.flags & TypeFlags.StringMapping ? left : right.flags & TypeFlags.StringMapping && str === applyStringMapping(right.symbol, str) ? source :
left.flags & TypeFlags.StringLiteral ? left : right.flags & TypeFlags.StringLiteral && (right as StringLiteralType).value === str ? right :
left.flags & TypeFlags.Number ? left : right.flags & TypeFlags.Number ? getNumberLiteralType(+str) :
left.flags & TypeFlags.Enum ? left : right.flags & TypeFlags.Enum ? getNumberLiteralType(+str) :
left.flags & TypeFlags.NumberLiteral ? left : right.flags & TypeFlags.NumberLiteral && (right as NumberLiteralType).value === +str ? right :
left.flags & TypeFlags.BigInt ? left : right.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) :
left.flags & TypeFlags.BigIntLiteral ? left : right.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((right as BigIntLiteralType).value) === str ? right :
left.flags & TypeFlags.Boolean ? left : right.flags & TypeFlags.Boolean ? str === "true" ? trueType : str === "false" ? falseType : booleanType :
left.flags & TypeFlags.BooleanLiteral ? left : right.flags & TypeFlags.BooleanLiteral && (right as IntrinsicType).intrinsicName === str ? right :
left.flags & TypeFlags.Undefined ? left : right.flags & TypeFlags.Undefined && (right as IntrinsicType).intrinsicName === str ? right :
left.flags & TypeFlags.Null ? left : right.flags & TypeFlags.Null && (right as IntrinsicType).intrinsicName === str ? right :
left,
neverType as Type);
if (!(matchingType.flags & TypeFlags.Never)) {
inferFromTypes(matchingType, target);
continue;
}
}
}
}
inferFromTypes(source, target);
}
}
}
@@ -23410,13 +23524,16 @@ namespace ts {
resolved.members.get("bind" as __String) && isTypeSubtypeOf(type, globalFunctionType));
}
function getTypeFacts(type: Type, ignoreObjects = false): TypeFacts {
function getTypeFacts(type: Type): TypeFacts {
if (type.flags & (TypeFlags.Intersection | TypeFlags.Instantiable)) {
type = getBaseConstraintOfType(type) || unknownType;
}
const flags = type.flags;
if (flags & TypeFlags.String) {
if (flags & (TypeFlags.String | TypeFlags.StringMapping)) {
return strictNullChecks ? TypeFacts.StringStrictFacts : TypeFacts.StringFacts;
}
if (flags & TypeFlags.StringLiteral) {
const isEmpty = (type as StringLiteralType).value === "";
if (flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral)) {
const isEmpty = flags & TypeFlags.StringLiteral && (type as StringLiteralType).value === "";
return strictNullChecks ?
isEmpty ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts :
isEmpty ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts;
@@ -23448,16 +23565,16 @@ namespace ts {
(type === falseType || type === regularFalseType) ? TypeFacts.FalseFacts : TypeFacts.TrueFacts;
}
if (flags & TypeFlags.Object) {
if (ignoreObjects) {
return TypeFacts.AndFactsMask; // This is the identity element for computing type facts of intersection.
}
return getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type as ObjectType) ?
strictNullChecks ? TypeFacts.EmptyObjectStrictFacts : TypeFacts.EmptyObjectFacts :
isFunctionObjectType(type as ObjectType) ?
strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts :
strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
}
if (flags & (TypeFlags.Void | TypeFlags.Undefined)) {
if (flags & TypeFlags.Void) {
return TypeFacts.VoidFacts;
}
if (flags & TypeFlags.Undefined) {
return TypeFacts.UndefinedFacts;
}
if (flags & TypeFlags.Null) {
@@ -23472,31 +23589,29 @@ namespace ts {
if (flags & TypeFlags.Never) {
return TypeFacts.None;
}
if (flags & TypeFlags.Instantiable) {
return !isPatternLiteralType(type) ? getTypeFacts(getBaseConstraintOfType(type) || unknownType, ignoreObjects) :
strictNullChecks ? TypeFacts.NonEmptyStringStrictFacts : TypeFacts.NonEmptyStringFacts;
}
if (flags & TypeFlags.Union) {
return reduceLeft((type as UnionType).types, (facts, t) => facts | getTypeFacts(t, ignoreObjects), TypeFacts.None);
return reduceLeft((type as UnionType).types, (facts, t) => facts | getTypeFacts(t), TypeFacts.None);
}
if (flags & TypeFlags.Intersection) {
// When an intersection contains a primitive type we ignore object type constituents as they are
// presumably type tags. For example, in string & { __kind__: "name" } we ignore the object type.
ignoreObjects ||= maybeTypeOfKind(type, TypeFlags.Primitive);
return getIntersectionTypeFacts(type as IntersectionType, ignoreObjects);
return getIntersectionTypeFacts(type as IntersectionType);
}
return TypeFacts.All;
return TypeFacts.UnknownFacts;
}
function getIntersectionTypeFacts(type: IntersectionType, ignoreObjects: boolean): TypeFacts {
function getIntersectionTypeFacts(type: IntersectionType): TypeFacts {
// When an intersection contains a primitive type we ignore object type constituents as they are
// presumably type tags. For example, in string & { __kind__: "name" } we ignore the object type.
const ignoreObjects = maybeTypeOfKind(type, TypeFlags.Primitive);
// When computing the type facts of an intersection type, certain type facts are computed as `and`
// and others are computed as `or`.
let oredFacts = TypeFacts.None;
let andedFacts = TypeFacts.All;
for (const t of type.types) {
const f = getTypeFacts(t, ignoreObjects);
oredFacts |= f;
andedFacts &= f;
if (!(ignoreObjects && t.flags & TypeFlags.Object)) {
const f = getTypeFacts(t);
oredFacts |= f;
andedFacts &= f;
}
}
return oredFacts & TypeFacts.OrFactsMask | andedFacts & TypeFacts.AndFactsMask;
}
@@ -23505,6 +23620,29 @@ namespace ts {
return filterType(type, t => (getTypeFacts(t) & include) !== 0);
}
// This function is similar to getTypeWithFacts, except that in strictNullChecks mode it replaces type
// unknown with the union {} | null | undefined (and reduces that accordingly), and it intersects remaining
// instantiable types with {}, {} | null, or {} | undefined in order to remove null and/or undefined.
function getAdjustedTypeWithFacts(type: Type, facts: TypeFacts) {
const reduced = recombineUnknownType(getTypeWithFacts(strictNullChecks && type.flags & TypeFlags.Unknown ? unknownUnionType : type, facts));
if (strictNullChecks) {
switch (facts) {
case TypeFacts.NEUndefined:
return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQUndefined ? getIntersectionType([t, getTypeFacts(t) & TypeFacts.EQNull && !maybeTypeOfKind(reduced, TypeFlags.Null) ? getUnionType([emptyObjectType, nullType]) : emptyObjectType]): t);
case TypeFacts.NENull:
return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQNull ? getIntersectionType([t, getTypeFacts(t) & TypeFacts.EQUndefined && !maybeTypeOfKind(reduced, TypeFlags.Undefined) ? getUnionType([emptyObjectType, undefinedType]) : emptyObjectType]): t);
case TypeFacts.NEUndefinedOrNull:
case TypeFacts.Truthy:
return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQUndefinedOrNull ? getGlobalNonNullableTypeInstantiation(t): t);
}
}
return reduced;
}
function recombineUnknownType(type: Type) {
return type === unknownUnionType ? unknownType : type;
}
function getTypeWithDefault(type: Type, defaultExpression: Expression) {
return defaultExpression ?
getUnionType([getNonUndefinedType(type), getTypeOfExpression(defaultExpression)]) :
@@ -24636,7 +24774,7 @@ namespace ts {
if (isEvolvingArrayTypeList(types)) {
return getEvolvingArrayType(getUnionType(map(types, getElementTypeOfEvolvingArrayType)));
}
const result = getUnionType(sameMap(types, finalizeEvolvingArrayType), subtypeReduction);
const result = recombineUnknownType(getUnionType(sameMap(types, finalizeEvolvingArrayType), subtypeReduction));
if (result !== declaredType && result.flags & declaredType.flags & TypeFlags.Union && arraysEqual((result as UnionType).types, (declaredType as UnionType).types)) {
return declaredType;
}
@@ -24744,11 +24882,10 @@ namespace ts {
function narrowTypeByTruthiness(type: Type, expr: Expression, assumeTrue: boolean): Type {
if (isMatchingReference(reference, expr)) {
return type.flags & TypeFlags.Unknown && assumeTrue ? nonNullUnknownType :
getTypeWithFacts(type, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy);
return getAdjustedTypeWithFacts(type, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy);
}
if (strictNullChecks && assumeTrue && optionalChainContainsReference(expr, reference)) {
type = getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
type = getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
}
const access = getDiscriminantPropertyAccess(expr, type);
if (access) {
@@ -24894,7 +25031,7 @@ namespace ts {
// Note that we include any and unknown in the exclusion test because their domain includes null and undefined.
const removeNullable = equalsOperator !== assumeTrue && everyType(valueType, t => !!(t.flags & nullableFlags)) ||
equalsOperator === assumeTrue && everyType(valueType, t => !(t.flags & (TypeFlags.AnyOrUnknown | nullableFlags)));
return removeNullable ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
return removeNullable ? getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
}
function narrowTypeByEquality(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type {
@@ -24905,9 +25042,6 @@ namespace ts {
assumeTrue = !assumeTrue;
}
const valueType = getTypeOfExpression(value);
if (assumeTrue && (type.flags & TypeFlags.Unknown) && (operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken) && (valueType.flags & TypeFlags.Null)) {
return getUnionType([nullType, undefinedType]);
}
if ((type.flags & TypeFlags.Unknown) && assumeTrue && (operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken)) {
if (valueType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive)) {
return valueType;
@@ -24927,7 +25061,7 @@ namespace ts {
valueType.flags & TypeFlags.Null ?
assumeTrue ? TypeFacts.EQNull : TypeFacts.NENull :
assumeTrue ? TypeFacts.EQUndefined : TypeFacts.NEUndefined;
return type.flags & TypeFlags.Unknown && facts & (TypeFacts.NENull | TypeFacts.NEUndefinedOrNull) ? nonNullUnknownType : getTypeWithFacts(type, facts);
return getAdjustedTypeWithFacts(type, facts);
}
if (assumeTrue) {
const filterFn: (t: Type) => boolean = operator === SyntaxKind.EqualsEqualsToken ?
@@ -24949,24 +25083,18 @@ namespace ts {
const target = getReferenceCandidate(typeOfExpr.expression);
if (!isMatchingReference(reference, target)) {
if (strictNullChecks && optionalChainContainsReference(target, reference) && assumeTrue === (literal.text !== "undefined")) {
return getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
return getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
}
return type;
}
if (type.flags & TypeFlags.Any && literal.text === "function") {
return type;
}
if (assumeTrue && type.flags & TypeFlags.Unknown && literal.text === "object") {
// The non-null unknown type is used to track whether a previous narrowing operation has removed the null type
// from the unknown type. For example, the expression `x && typeof x === 'object'` first narrows x to the non-null
// unknown type, and then narrows that to the non-primitive type.
return type === nonNullUnknownType ? nonPrimitiveType : getUnionType([nonPrimitiveType, nullType]);
}
const facts = assumeTrue ?
typeofEQFacts.get(literal.text) || TypeFacts.TypeofEQHostObject :
typeofNEFacts.get(literal.text) || TypeFacts.TypeofNEHostObject;
const impliedType = getImpliedTypeFromTypeofGuard(type, literal.text);
return getTypeWithFacts(assumeTrue && impliedType ? mapType(type, narrowUnionMemberByTypeof(impliedType)) : type, facts);
return getTypeWithFacts(assumeTrue && impliedType ? narrowTypeByImpliedType(type, impliedType) : type, facts);
}
function narrowTypeBySwitchOptionalChainContainment(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number, clauseCheck: (type: Type) => boolean) {
@@ -25019,10 +25147,10 @@ namespace ts {
function getImpliedTypeFromTypeofGuard(type: Type, text: string) {
switch (text) {
case "object":
return type.flags & TypeFlags.Any ? type : getUnionType([nullType, nonPrimitiveType]);
case "function":
return type.flags & TypeFlags.Any ? type : globalFunctionType;
case "object":
return type.flags & TypeFlags.Unknown ? getUnionType([nonPrimitiveType, nullType]) : type;
default:
return typeofTypesByName.get(text);
}
@@ -25034,22 +25162,27 @@ namespace ts {
// the guard. For example: narrowing `{} | undefined` by `"boolean"` should produce the type `boolean`, not
// the filtered type `{}`. For this reason we narrow constituents of the union individually, in addition to
// filtering by type-facts.
function narrowUnionMemberByTypeof(candidate: Type) {
return (type: Type) => {
if (isTypeSubtypeOf(type, candidate)) {
return type;
function narrowTypeByImpliedType(type: Type, candidate: Type) {
if (type.flags & TypeFlags.AnyOrUnknown) {
return candidate;
}
return mapType(type, t => {
if (isTypeRelatedTo(t, candidate, strictSubtypeRelation)) {
return t;
}
if (isTypeSubtypeOf(candidate, type)) {
return candidate;
}
if (type.flags & TypeFlags.Instantiable) {
const constraint = getBaseConstraintOfType(type) || anyType;
if (isTypeSubtypeOf(candidate, constraint)) {
return getIntersectionType([type, candidate]);
return mapType(candidate, c => {
if (!areTypesComparable(t, c)) {
return neverType;
}
}
return type;
};
if (c.flags & TypeFlags.Primitive && t.flags & TypeFlags.Object && !isEmptyAnonymousObjectType(t)) {
return isTypeSubtypeOf(c, t) ? c : neverType;
}
if (c === globalFunctionType && isTypeSubtypeOf(c, t)) {
return c;
}
return getIntersectionType([t, c]);
});
});
}
function narrowBySwitchOnTypeOf(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): Type {
@@ -25109,7 +25242,7 @@ namespace ts {
because it is caught in the first clause.
*/
const impliedType = getTypeWithFacts(getUnionType(clauseWitnesses.map(text => getImpliedTypeFromTypeofGuard(type, text) || type)), switchFacts);
return getTypeWithFacts(mapType(type, narrowUnionMemberByTypeof(impliedType)), switchFacts);
return getTypeWithFacts(narrowTypeByImpliedType(type, impliedType), switchFacts);
}
function isMatchingConstructorReference(expr: Expression) {
@@ -25170,7 +25303,7 @@ namespace ts {
const left = getReferenceCandidate(expr.left);
if (!isMatchingReference(reference, left)) {
if (assumeTrue && strictNullChecks && optionalChainContainsReference(left, reference)) {
return getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
return getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
}
return type;
}
@@ -25267,7 +25400,7 @@ namespace ts {
}
if (strictNullChecks && assumeTrue && optionalChainContainsReference(predicateArgument, reference) &&
!(getTypeFacts(predicate.type) & TypeFacts.EQUndefined)) {
type = getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
type = getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
}
const access = getDiscriminantPropertyAccess(predicateArgument, type);
if (access) {
@@ -25326,7 +25459,7 @@ namespace ts {
function narrowTypeByOptionality(type: Type, expr: Expression, assumePresent: boolean): Type {
if (isMatchingReference(reference, expr)) {
return getTypeWithFacts(type, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull);
return getAdjustedTypeWithFacts(type, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull);
}
const access = getDiscriminantPropertyAccess(expr, type);
if (access) {
@@ -25418,8 +25551,8 @@ namespace ts {
const annotationIncludesUndefined = strictNullChecks &&
declaration.kind === SyntaxKind.Parameter &&
declaration.initializer &&
getFalsyFlags(declaredType) & TypeFlags.Undefined &&
!(getFalsyFlags(checkExpression(declaration.initializer)) & TypeFlags.Undefined);
getTypeFacts(declaredType) & TypeFacts.IsUndefined &&
!(getTypeFacts(checkExpression(declaration.initializer)) & TypeFacts.IsUndefined);
popTypeResolution();
return annotationIncludesUndefined ? getTypeWithFacts(declaredType, TypeFacts.NEUndefined) : declaredType;
@@ -25442,8 +25575,10 @@ namespace ts {
!(someType(type, isGenericTypeWithoutNullableConstraint) && isGenericIndexType(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression)));
}
function isGenericTypeWithUnionConstraint(type: Type) {
return !!(type.flags & TypeFlags.Instantiable && getBaseConstraintOrType(type).flags & (TypeFlags.Nullable | TypeFlags.Union));
function isGenericTypeWithUnionConstraint(type: Type): boolean {
return type.flags & TypeFlags.Intersection ?
some((type as IntersectionType).types, isGenericTypeWithUnionConstraint) :
!!(type.flags & TypeFlags.Instantiable && getBaseConstraintOrType(type).flags & (TypeFlags.Nullable | TypeFlags.Union));
}
function isGenericTypeWithoutNullableConstraint(type: Type) {
@@ -25474,7 +25609,7 @@ namespace ts {
const substituteConstraints = !(checkMode && checkMode & CheckMode.Inferential) &&
someType(type, isGenericTypeWithUnionConstraint) &&
(isConstraintPosition(type, reference) || hasContextualTypeWithNoGenericTypes(reference, checkMode));
return substituteConstraints ? mapType(type, t => t.flags & TypeFlags.Instantiable ? getBaseConstraintOrType(t) : t) : type;
return substituteConstraints ? mapType(type, getBaseConstraintOrType) : type;
}
function isExportOrExportExpression(location: Node) {
@@ -25774,7 +25909,7 @@ namespace ts {
return convertAutoToAny(flowType);
}
}
else if (!assumeInitialized && !(getFalsyFlags(type) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) {
else if (!assumeInitialized && !(getTypeFacts(type) & TypeFacts.IsUndefined) && getTypeFacts(flowType) & TypeFacts.IsUndefined) {
error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
// Return the declared type to reduce follow-on errors
return type;
@@ -28751,23 +28886,23 @@ namespace ts {
}
function isNullableType(type: Type) {
return !!((strictNullChecks ? getFalsyFlags(type) : type.flags) & TypeFlags.Nullable);
return !!(getTypeFacts(type) & TypeFacts.IsUndefinedOrNull);
}
function getNonNullableTypeIfNeeded(type: Type) {
return isNullableType(type) ? getNonNullableType(type) : type;
}
function reportObjectPossiblyNullOrUndefinedError(node: Node, flags: TypeFlags) {
error(node, flags & TypeFlags.Undefined ? flags & TypeFlags.Null ?
function reportObjectPossiblyNullOrUndefinedError(node: Node, facts: TypeFacts) {
error(node, facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ?
Diagnostics.Object_is_possibly_null_or_undefined :
Diagnostics.Object_is_possibly_undefined :
Diagnostics.Object_is_possibly_null
);
}
function reportCannotInvokePossiblyNullOrUndefinedError(node: Node, flags: TypeFlags) {
error(node, flags & TypeFlags.Undefined ? flags & TypeFlags.Null ?
function reportCannotInvokePossiblyNullOrUndefinedError(node: Node, facts: TypeFacts) {
error(node, facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ?
Diagnostics.Cannot_invoke_an_object_which_is_possibly_null_or_undefined :
Diagnostics.Cannot_invoke_an_object_which_is_possibly_undefined :
Diagnostics.Cannot_invoke_an_object_which_is_possibly_null
@@ -28777,15 +28912,15 @@ namespace ts {
function checkNonNullTypeWithReporter(
type: Type,
node: Node,
reportError: (node: Node, kind: TypeFlags) => void
reportError: (node: Node, facts: TypeFacts) => void
): Type {
if (strictNullChecks && type.flags & TypeFlags.Unknown) {
error(node, Diagnostics.Object_is_of_type_unknown);
return errorType;
}
const kind = (strictNullChecks ? getFalsyFlags(type) : type.flags) & TypeFlags.Nullable;
if (kind) {
reportError(node, kind);
const facts = getTypeFacts(type);
if (facts & TypeFacts.IsUndefinedOrNull) {
reportError(node, facts);
const t = getNonNullableType(type);
return t.flags & (TypeFlags.Nullable | TypeFlags.Never) ? errorType : t;
}
@@ -29131,7 +29266,7 @@ namespace ts {
assumeUninitialized = true;
}
const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType);
if (assumeUninitialized && !(getFalsyFlags(propType) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) {
if (assumeUninitialized && !(getTypeFacts(propType) & TypeFacts.IsUndefined) && getTypeFacts(flowType) & TypeFacts.IsUndefined) {
error(errorNode, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217
// Return the declared type to reduce follow-on errors
return propType;
@@ -33118,7 +33253,7 @@ namespace ts {
const type = getTypeOfSymbol(symbol);
if (strictNullChecks &&
!(type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Never)) &&
!(exactOptionalPropertyTypes ? symbol.flags & SymbolFlags.Optional : getFalsyFlags(type) & TypeFlags.Undefined)) {
!(exactOptionalPropertyTypes ? symbol.flags & SymbolFlags.Optional : getTypeFacts(type) & TypeFacts.IsUndefined)) {
error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_optional);
}
}
@@ -33555,7 +33690,7 @@ namespace ts {
// In strict null checking mode, if a default value of a non-undefined type is specified, remove
// undefined from the final type.
if (strictNullChecks &&
!(getFalsyFlags(checkExpression(prop.objectAssignmentInitializer)) & TypeFlags.Undefined)) {
!(getTypeFacts(checkExpression(prop.objectAssignmentInitializer)) & TypeFacts.IsUndefined)) {
sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined);
}
checkBinaryLikeExpression(prop.name, prop.equalsToken!, prop.objectAssignmentInitializer, checkMode);
@@ -34014,7 +34149,7 @@ namespace ts {
case SyntaxKind.BarBarToken:
case SyntaxKind.BarBarEqualsToken: {
const resultType = getTypeFacts(leftType) & TypeFacts.Falsy ?
getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], UnionReduction.Subtype) :
getUnionType([getNonNullableType(removeDefinitelyFalsyTypes(leftType)), rightType], UnionReduction.Subtype) :
leftType;
if (operator === SyntaxKind.BarBarEqualsToken) {
checkAssignmentOperator(rightType);
@@ -37793,7 +37928,7 @@ namespace ts {
// For a binding pattern, validate the initializer and exit
if (isBindingPattern(node.name)) {
const needCheckInitializer = node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement;
const needCheckWidenedType = node.name.elements.length === 0;
const needCheckWidenedType = !some(node.name.elements, not(isOmittedExpression));
if (needCheckInitializer || needCheckWidenedType) {
// Don't validate for-in initializer as it is already an error
const widenedType = getWidenedTypeForVariableLikeDeclaration(node);
@@ -37969,7 +38104,7 @@ namespace ts {
if (isModuleExportsAccessExpression(location)) return;
const type = checkTruthinessExpression(location);
const isPropertyExpressionCast = isPropertyAccessExpression(location) && isTypeAssertion(location.expression);
if (getFalsyFlags(type) || isPropertyExpressionCast) return;
if (!(getTypeFacts(type) & TypeFacts.Truthy) || isPropertyExpressionCast) return;
// While it technically should be invalid for any known-truthy value
// to be tested, we de-scope to functions and Promises unreferenced in
@@ -39962,10 +40097,13 @@ namespace ts {
const derivedPropertyFlags = derived.flags & SymbolFlags.PropertyOrAccessor;
if (basePropertyFlags && derivedPropertyFlags) {
// property/accessor is overridden with property/accessor
if (baseDeclarationFlags & ModifierFlags.Abstract && !(base.valueDeclaration && isPropertyDeclaration(base.valueDeclaration) && base.valueDeclaration.initializer)
|| base.valueDeclaration && base.valueDeclaration.parent.kind === SyntaxKind.InterfaceDeclaration
if ((getCheckFlags(base) & CheckFlags.Synthetic
? base.declarations?.some(d => isPropertyAbstractOrInterface(d, baseDeclarationFlags))
: base.declarations?.every(d => isPropertyAbstractOrInterface(d, baseDeclarationFlags)))
|| getCheckFlags(base) & CheckFlags.Mapped
|| derived.valueDeclaration && isBinaryExpression(derived.valueDeclaration)) {
// when the base property is abstract or from an interface, base/derived flags don't need to match
// for intersection properties, this must be true of *any* of the declarations, for others it must be true of *all*
// same when the derived property is from an assignment
continue;
}
@@ -40023,7 +40161,12 @@ namespace ts {
}
}
function getNonInterhitedProperties(type: InterfaceType, baseTypes: BaseType[], properties: Symbol[]) {
function isPropertyAbstractOrInterface(declaration: Declaration, baseDeclarationFlags: ModifierFlags) {
return baseDeclarationFlags & ModifierFlags.Abstract && (!isPropertyDeclaration(declaration) || !declaration.initializer)
|| isInterfaceDeclaration(declaration.parent);
}
function getNonInheritedProperties(type: InterfaceType, baseTypes: BaseType[], properties: Symbol[]) {
if (!length(baseTypes)) {
return properties;
}
@@ -40097,7 +40240,7 @@ namespace ts {
const propName = (member as PropertyDeclaration).name;
if (isIdentifier(propName) || isPrivateIdentifier(propName) || isComputedPropertyName(propName)) {
const type = getTypeOfSymbol(getSymbolOfNode(member));
if (!(type.flags & TypeFlags.AnyOrUnknown || getFalsyFlags(type) & TypeFlags.Undefined)) {
if (!(type.flags & TypeFlags.AnyOrUnknown || getTypeFacts(type) & TypeFacts.IsUndefined)) {
if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) {
error(member.name, Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, declarationNameToString(propName));
}
@@ -40123,7 +40266,7 @@ namespace ts {
setParent(reference, staticBlock);
reference.flowNode = staticBlock.returnFlowNode;
const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType));
if (!(getFalsyFlags(flowType) & TypeFlags.Undefined)) {
if (!(getTypeFacts(flowType) & TypeFacts.IsUndefined)) {
return true;
}
}
@@ -40139,7 +40282,7 @@ namespace ts {
setParent(reference, constructor);
reference.flowNode = constructor.returnFlowNode;
const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType));
return !(getFalsyFlags(flowType) & TypeFlags.Undefined);
return !(getTypeFacts(flowType) & TypeFacts.IsUndefined);
}
+1 -1
View File
@@ -2035,7 +2035,7 @@ namespace ts {
return comparer(a, b);
}
export function compareProperties<T, K extends keyof T>(a: T | undefined, b: T | undefined, key: K, comparer: Comparer<T[K]>): Comparison {
export function compareProperties<T extends object, K extends keyof T>(a: T | undefined, b: T | undefined, key: K, comparer: Comparer<T[K]>): Comparison {
return a === b ? Comparison.EqualTo :
a === undefined ? Comparison.LessThan :
b === undefined ? Comparison.GreaterThan :
+8
View File
@@ -1526,6 +1526,10 @@
"category": "Error",
"code": 2207
},
"This type parameter probably needs an `extends object` constraint.": {
"category": "Error",
"code": 2208
},
"The project root is ambiguous, but is required to resolve export map entry '{0}' in file '{1}'. Supply the `rootDir` compiler option to disambiguate.": {
"category": "Error",
@@ -3471,6 +3475,10 @@
"category": "Error",
"code": 2839
},
"An interface cannot extend a primitive type like '{0}'; an interface can only extend named types and classes": {
"category": "Error",
"code": 2840
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
+2 -2
View File
@@ -2413,8 +2413,8 @@ namespace ts {
);
if (
!pathAndExtension && packageInfo
&& packageInfo.packageJsonContent.exports === undefined
&& packageInfo.packageJsonContent.main === undefined
// eslint-disable-next-line no-null/no-null
&& (packageInfo.packageJsonContent.exports === undefined || packageInfo.packageJsonContent.exports === null)
&& state.features & NodeResolutionFeatures.EsmMode
) {
// EsmMode disables index lookup in `loadNodeModuleFromDirectoryWorker` generally, however non-relative package resolutions still assume
+6 -1
View File
@@ -5398,6 +5398,11 @@ namespace ts {
// Flags that require TypeFlags.Union
/* @internal */
ContainsIntersections = 1 << 24, // Union contains intersections
/* @internal */
IsUnknownLikeUnionComputed = 1 << 25, // IsUnknownLikeUnion flag has been computed
/* @internal */
IsUnknownLikeUnion = 1 << 26, // Union of null, undefined, and empty object type
/* @internal */
// Flags that require TypeFlags.Intersection
/* @internal */
@@ -5878,7 +5883,7 @@ namespace ts {
AlwaysStrict = 1 << 10, // Always use strict rules for contravariant inferences
MaxValue = 1 << 11, // Seed for inference priority tracking
PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof, // These priorities imply that the resulting type should be a combination of all candidates
PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof, // These priorities imply that the resulting type should be a combination of all candidates
Circularity = -1, // Inference circularity (value less than all other priorities)
}
+1 -1
View File
@@ -1564,7 +1564,7 @@ type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
/**
* Exclude null and undefined from T
*/
type NonNullable<T> = T extends null | undefined ? never : T;
type NonNullable<T> = T & {};
/**
* Obtain the parameters of a function type in a tuple
@@ -13803,6 +13803,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[此类型参数可能需要 "extends object" 约束。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
@@ -13803,6 +13803,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[此類型參數可能需要 'extends object' 限制式。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
@@ -13812,6 +13812,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Tento parametr typu pravděpodobně potřebuje omezení „extends object“.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
@@ -13797,6 +13797,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Dieser Typparameter benötigt wahrscheinlich eine „extends object“-Einschränkung.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
@@ -13815,6 +13815,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Puede que este parámetro de tipo necesite una restricción “extends object”.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
@@ -13815,6 +13815,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Ce paramètre de type nécessite probablement une contrainte 'extends object'.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
@@ -13803,6 +13803,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Questo parametro di tipo richiede probabilmente un vincolo 'extends object'.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
@@ -13803,6 +13803,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[この型パラメーターには、`extends object` 制約が必要な可能性があります。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
@@ -13803,6 +13803,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[이 형식 매개 변수에는 `extends object` 제약 조건이 필요할 수 있습니다.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
@@ -13790,6 +13790,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Ten parametr typu prawdopodobnie wymaga ograniczenia „extends object”.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
@@ -13793,6 +13793,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Esse parâmetro de tipo provavelmente precisa de uma restrição `extends object.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
@@ -13802,6 +13802,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Возможно, для этого параметра типа требуется ограничение "extends object".]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
@@ -13796,6 +13796,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_type_parameter_probably_needs_an_extends_object_constraint_2208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This type parameter probably needs an `extends object` constraint.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Bu tür parametresi için bir `nesneyi genişletir` kısıtlaması gerekiyor olabilir.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments.]]></Val>
+19 -2
View File
@@ -617,7 +617,6 @@ namespace ts.formatting {
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxClosingElement:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.ExpressionWithTypeArguments:
return false;
}
break;
@@ -835,7 +834,7 @@ namespace ts.formatting {
const listEndToken = getCloseTokenForOpenToken(listStartToken);
if (listEndToken !== SyntaxKind.Unknown && formattingScanner.isOnToken() && formattingScanner.getStartPos() < originalRange.end) {
let tokenInfo: TokenInfo | undefined = formattingScanner.readTokenInfo(parent);
if (tokenInfo.token.kind === SyntaxKind.CommaToken && isCallLikeExpression(parent)) {
if (tokenInfo.token.kind === SyntaxKind.CommaToken) {
// consume the comma
consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent);
tokenInfo = formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(parent) : undefined;
@@ -1311,6 +1310,12 @@ namespace ts.formatting {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.ArrowFunction:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
if ((node as FunctionDeclaration).typeParameters === list) {
return SyntaxKind.LessThanToken;
}
@@ -1327,7 +1332,19 @@ namespace ts.formatting {
return SyntaxKind.OpenParenToken;
}
break;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
if ((node as ClassDeclaration).typeParameters === list) {
return SyntaxKind.LessThanToken;
}
break;
case SyntaxKind.TypeReference:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.TypeQuery:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.ImportType:
if ((node as TypeReferenceNode).typeArguments === list) {
return SyntaxKind.LessThanToken;
}
+1 -1
View File
@@ -47,7 +47,7 @@ namespace ts.InlayHints {
return;
}
if (isTypeNode(node)) {
if (isTypeNode(node) && !isExpressionWithTypeArguments(node)) {
return;
}
+9
View File
@@ -0,0 +1,9 @@
"use strict";
exports.__esModule = true;
exports.main = void 0;
function main() {
for (var _i = 0, doesNotExist_1 = doesNotExist; _i < doesNotExist_1.length; _i++) {
var _a = doesNotExist_1[_i];
}
}
exports.main = main;
+4
View File
@@ -0,0 +1,4 @@
export function main() {
for (const [,] of doesNotExist) {
}
}
@@ -0,0 +1,50 @@
//// [accessorsOverrideProperty8.ts]
type Types = 'boolean' | 'unknown' | 'string';
type Properties<T extends { [key: string]: Types }> = {
readonly [key in keyof T]: T[key] extends 'boolean' ? boolean : T[key] extends 'string' ? string : unknown
}
type AnyCtor<P extends object> = new (...a: any[]) => P
declare function classWithProperties<T extends { [key: string]: Types }, P extends object>(properties: T, klass: AnyCtor<P>): {
new(): P & Properties<T>;
prototype: P & Properties<T>
};
const Base = classWithProperties({
get x() { return 'boolean' as const },
y: 'string',
}, class Base {
});
class MyClass extends Base {
get x() {
return false;
}
get y() {
return 'hi'
}
}
const mine = new MyClass();
const value = mine.x;
//// [accessorsOverrideProperty8.js]
const Base = classWithProperties({
get x() { return 'boolean'; },
y: 'string',
}, class Base {
});
class MyClass extends Base {
get x() {
return false;
}
get y() {
return 'hi';
}
}
const mine = new MyClass();
const value = mine.x;
@@ -0,0 +1,93 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty8.ts ===
type Types = 'boolean' | 'unknown' | 'string';
>Types : Symbol(Types, Decl(accessorsOverrideProperty8.ts, 0, 0))
type Properties<T extends { [key: string]: Types }> = {
>Properties : Symbol(Properties, Decl(accessorsOverrideProperty8.ts, 0, 46))
>T : Symbol(T, Decl(accessorsOverrideProperty8.ts, 2, 16))
>key : Symbol(key, Decl(accessorsOverrideProperty8.ts, 2, 29))
>Types : Symbol(Types, Decl(accessorsOverrideProperty8.ts, 0, 0))
readonly [key in keyof T]: T[key] extends 'boolean' ? boolean : T[key] extends 'string' ? string : unknown
>key : Symbol(key, Decl(accessorsOverrideProperty8.ts, 3, 14))
>T : Symbol(T, Decl(accessorsOverrideProperty8.ts, 2, 16))
>T : Symbol(T, Decl(accessorsOverrideProperty8.ts, 2, 16))
>key : Symbol(key, Decl(accessorsOverrideProperty8.ts, 3, 14))
>T : Symbol(T, Decl(accessorsOverrideProperty8.ts, 2, 16))
>key : Symbol(key, Decl(accessorsOverrideProperty8.ts, 3, 14))
}
type AnyCtor<P extends object> = new (...a: any[]) => P
>AnyCtor : Symbol(AnyCtor, Decl(accessorsOverrideProperty8.ts, 4, 1))
>P : Symbol(P, Decl(accessorsOverrideProperty8.ts, 6, 13))
>a : Symbol(a, Decl(accessorsOverrideProperty8.ts, 6, 38))
>P : Symbol(P, Decl(accessorsOverrideProperty8.ts, 6, 13))
declare function classWithProperties<T extends { [key: string]: Types }, P extends object>(properties: T, klass: AnyCtor<P>): {
>classWithProperties : Symbol(classWithProperties, Decl(accessorsOverrideProperty8.ts, 6, 55))
>T : Symbol(T, Decl(accessorsOverrideProperty8.ts, 8, 37))
>key : Symbol(key, Decl(accessorsOverrideProperty8.ts, 8, 50))
>Types : Symbol(Types, Decl(accessorsOverrideProperty8.ts, 0, 0))
>P : Symbol(P, Decl(accessorsOverrideProperty8.ts, 8, 72))
>properties : Symbol(properties, Decl(accessorsOverrideProperty8.ts, 8, 91))
>T : Symbol(T, Decl(accessorsOverrideProperty8.ts, 8, 37))
>klass : Symbol(klass, Decl(accessorsOverrideProperty8.ts, 8, 105))
>AnyCtor : Symbol(AnyCtor, Decl(accessorsOverrideProperty8.ts, 4, 1))
>P : Symbol(P, Decl(accessorsOverrideProperty8.ts, 8, 72))
new(): P & Properties<T>;
>P : Symbol(P, Decl(accessorsOverrideProperty8.ts, 8, 72))
>Properties : Symbol(Properties, Decl(accessorsOverrideProperty8.ts, 0, 46))
>T : Symbol(T, Decl(accessorsOverrideProperty8.ts, 8, 37))
prototype: P & Properties<T>
>prototype : Symbol(prototype, Decl(accessorsOverrideProperty8.ts, 9, 29))
>P : Symbol(P, Decl(accessorsOverrideProperty8.ts, 8, 72))
>Properties : Symbol(Properties, Decl(accessorsOverrideProperty8.ts, 0, 46))
>T : Symbol(T, Decl(accessorsOverrideProperty8.ts, 8, 37))
};
const Base = classWithProperties({
>Base : Symbol(Base, Decl(accessorsOverrideProperty8.ts, 13, 5))
>classWithProperties : Symbol(classWithProperties, Decl(accessorsOverrideProperty8.ts, 6, 55))
get x() { return 'boolean' as const },
>x : Symbol(x, Decl(accessorsOverrideProperty8.ts, 13, 34))
>const : Symbol(const)
y: 'string',
>y : Symbol(y, Decl(accessorsOverrideProperty8.ts, 14, 42))
}, class Base {
>Base : Symbol(Base, Decl(accessorsOverrideProperty8.ts, 16, 2))
});
class MyClass extends Base {
>MyClass : Symbol(MyClass, Decl(accessorsOverrideProperty8.ts, 17, 3))
>Base : Symbol(Base, Decl(accessorsOverrideProperty8.ts, 13, 5))
get x() {
>x : Symbol(MyClass.x, Decl(accessorsOverrideProperty8.ts, 19, 28))
return false;
}
get y() {
>y : Symbol(MyClass.y, Decl(accessorsOverrideProperty8.ts, 22, 5))
return 'hi'
}
}
const mine = new MyClass();
>mine : Symbol(mine, Decl(accessorsOverrideProperty8.ts, 28, 5))
>MyClass : Symbol(MyClass, Decl(accessorsOverrideProperty8.ts, 17, 3))
const value = mine.x;
>value : Symbol(value, Decl(accessorsOverrideProperty8.ts, 29, 5))
>mine.x : Symbol(MyClass.x, Decl(accessorsOverrideProperty8.ts, 19, 28))
>mine : Symbol(mine, Decl(accessorsOverrideProperty8.ts, 28, 5))
>x : Symbol(MyClass.x, Decl(accessorsOverrideProperty8.ts, 19, 28))
@@ -0,0 +1,78 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty8.ts ===
type Types = 'boolean' | 'unknown' | 'string';
>Types : "string" | "boolean" | "unknown"
type Properties<T extends { [key: string]: Types }> = {
>Properties : Properties<T>
>key : string
readonly [key in keyof T]: T[key] extends 'boolean' ? boolean : T[key] extends 'string' ? string : unknown
}
type AnyCtor<P extends object> = new (...a: any[]) => P
>AnyCtor : AnyCtor<P>
>a : any[]
declare function classWithProperties<T extends { [key: string]: Types }, P extends object>(properties: T, klass: AnyCtor<P>): {
>classWithProperties : <T extends { [key: string]: Types; }, P extends object>(properties: T, klass: AnyCtor<P>) => { new (): P & Properties<T>; prototype: P & Properties<T>;}
>key : string
>properties : T
>klass : AnyCtor<P>
new(): P & Properties<T>;
prototype: P & Properties<T>
>prototype : P & Properties<T>
};
const Base = classWithProperties({
>Base : { new (): Base & Properties<{ readonly x: "boolean"; y: "string"; }>; prototype: Base & Properties<{ readonly x: "boolean"; y: "string"; }>; }
>classWithProperties({ get x() { return 'boolean' as const }, y: 'string',}, class Base {}) : { new (): Base & Properties<{ readonly x: "boolean"; y: "string"; }>; prototype: Base & Properties<{ readonly x: "boolean"; y: "string"; }>; }
>classWithProperties : <T extends { [key: string]: Types; }, P extends object>(properties: T, klass: AnyCtor<P>) => { new (): P & Properties<T>; prototype: P & Properties<T>; }
>{ get x() { return 'boolean' as const }, y: 'string',} : { readonly x: "boolean"; y: "string"; }
get x() { return 'boolean' as const },
>x : "boolean"
>'boolean' as const : "boolean"
>'boolean' : "boolean"
y: 'string',
>y : "string"
>'string' : "string"
}, class Base {
>class Base {} : typeof Base
>Base : typeof Base
});
class MyClass extends Base {
>MyClass : MyClass
>Base : Base & Properties<{ readonly x: "boolean"; y: "string"; }>
get x() {
>x : boolean
return false;
>false : false
}
get y() {
>y : string
return 'hi'
>'hi' : "hi"
}
}
const mine = new MyClass();
>mine : MyClass
>new MyClass() : MyClass
>MyClass : typeof MyClass
const value = mine.x;
>value : boolean
>mine.x : boolean
>mine : MyClass
>x : boolean
@@ -0,0 +1,79 @@
//// [accessorsOverrideProperty9.ts]
// #41347, based on microsoft/rushstack
// Mixin utilities
export type Constructor<T = {}> = new (...args: any[]) => T;
export type PropertiesOf<T> = { [K in keyof T]: T[K] };
interface IApiItemConstructor extends Constructor<ApiItem>, PropertiesOf<typeof ApiItem> {}
// Base class
class ApiItem {
public get members(): ReadonlyArray<ApiItem> {
return [];
}
}
// Normal subclass
class ApiEnumMember extends ApiItem {
}
// Mixin base class
interface ApiItemContainerMixin extends ApiItem {
readonly members: ReadonlyArray<ApiItem>;
}
function ApiItemContainerMixin<TBaseClass extends IApiItemConstructor>(
baseClass: TBaseClass
): TBaseClass & (new (...args: any[]) => ApiItemContainerMixin) {
abstract class MixedClass extends baseClass implements ApiItemContainerMixin {
public constructor(...args: any[]) {
super(...args);
}
public get members(): ReadonlyArray<ApiItem> {
return [];
}
}
return MixedClass;
}
// Subclass inheriting from mixin
export class ApiEnum extends ApiItemContainerMixin(ApiItem) {
// This worked prior to TypeScript 4.0:
public get members(): ReadonlyArray<ApiEnumMember> {
return [];
}
}
//// [accessorsOverrideProperty9.js]
// #41347, based on microsoft/rushstack
// Base class
class ApiItem {
get members() {
return [];
}
}
// Normal subclass
class ApiEnumMember extends ApiItem {
}
function ApiItemContainerMixin(baseClass) {
class MixedClass extends baseClass {
constructor(...args) {
super(...args);
}
get members() {
return [];
}
}
return MixedClass;
}
// Subclass inheriting from mixin
export class ApiEnum extends ApiItemContainerMixin(ApiItem) {
// This worked prior to TypeScript 4.0:
get members() {
return [];
}
}
@@ -0,0 +1,111 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty9.ts ===
// #41347, based on microsoft/rushstack
// Mixin utilities
export type Constructor<T = {}> = new (...args: any[]) => T;
>Constructor : Symbol(Constructor, Decl(accessorsOverrideProperty9.ts, 0, 0))
>T : Symbol(T, Decl(accessorsOverrideProperty9.ts, 3, 24))
>args : Symbol(args, Decl(accessorsOverrideProperty9.ts, 3, 39))
>T : Symbol(T, Decl(accessorsOverrideProperty9.ts, 3, 24))
export type PropertiesOf<T> = { [K in keyof T]: T[K] };
>PropertiesOf : Symbol(PropertiesOf, Decl(accessorsOverrideProperty9.ts, 3, 60))
>T : Symbol(T, Decl(accessorsOverrideProperty9.ts, 4, 25))
>K : Symbol(K, Decl(accessorsOverrideProperty9.ts, 4, 33))
>T : Symbol(T, Decl(accessorsOverrideProperty9.ts, 4, 25))
>T : Symbol(T, Decl(accessorsOverrideProperty9.ts, 4, 25))
>K : Symbol(K, Decl(accessorsOverrideProperty9.ts, 4, 33))
interface IApiItemConstructor extends Constructor<ApiItem>, PropertiesOf<typeof ApiItem> {}
>IApiItemConstructor : Symbol(IApiItemConstructor, Decl(accessorsOverrideProperty9.ts, 4, 55))
>Constructor : Symbol(Constructor, Decl(accessorsOverrideProperty9.ts, 0, 0))
>ApiItem : Symbol(ApiItem, Decl(accessorsOverrideProperty9.ts, 6, 91))
>PropertiesOf : Symbol(PropertiesOf, Decl(accessorsOverrideProperty9.ts, 3, 60))
>ApiItem : Symbol(ApiItem, Decl(accessorsOverrideProperty9.ts, 6, 91))
// Base class
class ApiItem {
>ApiItem : Symbol(ApiItem, Decl(accessorsOverrideProperty9.ts, 6, 91))
public get members(): ReadonlyArray<ApiItem> {
>members : Symbol(ApiItem.members, Decl(accessorsOverrideProperty9.ts, 9, 15))
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2016.array.include.d.ts, --, --))
>ApiItem : Symbol(ApiItem, Decl(accessorsOverrideProperty9.ts, 6, 91))
return [];
}
}
// Normal subclass
class ApiEnumMember extends ApiItem {
>ApiEnumMember : Symbol(ApiEnumMember, Decl(accessorsOverrideProperty9.ts, 13, 1))
>ApiItem : Symbol(ApiItem, Decl(accessorsOverrideProperty9.ts, 6, 91))
}
// Mixin base class
interface ApiItemContainerMixin extends ApiItem {
>ApiItemContainerMixin : Symbol(ApiItemContainerMixin, Decl(accessorsOverrideProperty9.ts, 22, 1), Decl(accessorsOverrideProperty9.ts, 17, 1))
>ApiItem : Symbol(ApiItem, Decl(accessorsOverrideProperty9.ts, 6, 91))
readonly members: ReadonlyArray<ApiItem>;
>members : Symbol(ApiItemContainerMixin.members, Decl(accessorsOverrideProperty9.ts, 20, 49))
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2016.array.include.d.ts, --, --))
>ApiItem : Symbol(ApiItem, Decl(accessorsOverrideProperty9.ts, 6, 91))
}
function ApiItemContainerMixin<TBaseClass extends IApiItemConstructor>(
>ApiItemContainerMixin : Symbol(ApiItemContainerMixin, Decl(accessorsOverrideProperty9.ts, 22, 1), Decl(accessorsOverrideProperty9.ts, 17, 1))
>TBaseClass : Symbol(TBaseClass, Decl(accessorsOverrideProperty9.ts, 24, 31))
>IApiItemConstructor : Symbol(IApiItemConstructor, Decl(accessorsOverrideProperty9.ts, 4, 55))
baseClass: TBaseClass
>baseClass : Symbol(baseClass, Decl(accessorsOverrideProperty9.ts, 24, 71))
>TBaseClass : Symbol(TBaseClass, Decl(accessorsOverrideProperty9.ts, 24, 31))
): TBaseClass & (new (...args: any[]) => ApiItemContainerMixin) {
>TBaseClass : Symbol(TBaseClass, Decl(accessorsOverrideProperty9.ts, 24, 31))
>args : Symbol(args, Decl(accessorsOverrideProperty9.ts, 26, 22))
>ApiItemContainerMixin : Symbol(ApiItemContainerMixin, Decl(accessorsOverrideProperty9.ts, 22, 1), Decl(accessorsOverrideProperty9.ts, 17, 1))
abstract class MixedClass extends baseClass implements ApiItemContainerMixin {
>MixedClass : Symbol(MixedClass, Decl(accessorsOverrideProperty9.ts, 26, 65))
>baseClass : Symbol(baseClass, Decl(accessorsOverrideProperty9.ts, 24, 71))
>ApiItemContainerMixin : Symbol(ApiItemContainerMixin, Decl(accessorsOverrideProperty9.ts, 22, 1), Decl(accessorsOverrideProperty9.ts, 17, 1))
public constructor(...args: any[]) {
>args : Symbol(args, Decl(accessorsOverrideProperty9.ts, 28, 23))
super(...args);
>super : Symbol(TBaseClass, Decl(accessorsOverrideProperty9.ts, 24, 31))
>args : Symbol(args, Decl(accessorsOverrideProperty9.ts, 28, 23))
}
public get members(): ReadonlyArray<ApiItem> {
>members : Symbol(MixedClass.members, Decl(accessorsOverrideProperty9.ts, 30, 5))
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2016.array.include.d.ts, --, --))
>ApiItem : Symbol(ApiItem, Decl(accessorsOverrideProperty9.ts, 6, 91))
return [];
}
}
return MixedClass;
>MixedClass : Symbol(MixedClass, Decl(accessorsOverrideProperty9.ts, 26, 65))
}
// Subclass inheriting from mixin
export class ApiEnum extends ApiItemContainerMixin(ApiItem) {
>ApiEnum : Symbol(ApiEnum, Decl(accessorsOverrideProperty9.ts, 38, 1))
>ApiItemContainerMixin : Symbol(ApiItemContainerMixin, Decl(accessorsOverrideProperty9.ts, 22, 1), Decl(accessorsOverrideProperty9.ts, 17, 1))
>ApiItem : Symbol(ApiItem, Decl(accessorsOverrideProperty9.ts, 6, 91))
// This worked prior to TypeScript 4.0:
public get members(): ReadonlyArray<ApiEnumMember> {
>members : Symbol(ApiEnum.members, Decl(accessorsOverrideProperty9.ts, 41, 61))
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2016.array.include.d.ts, --, --))
>ApiEnumMember : Symbol(ApiEnumMember, Decl(accessorsOverrideProperty9.ts, 13, 1))
return [];
}
}
@@ -0,0 +1,89 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty9.ts ===
// #41347, based on microsoft/rushstack
// Mixin utilities
export type Constructor<T = {}> = new (...args: any[]) => T;
>Constructor : Constructor<T>
>args : any[]
export type PropertiesOf<T> = { [K in keyof T]: T[K] };
>PropertiesOf : PropertiesOf<T>
interface IApiItemConstructor extends Constructor<ApiItem>, PropertiesOf<typeof ApiItem> {}
>ApiItem : typeof ApiItem
// Base class
class ApiItem {
>ApiItem : ApiItem
public get members(): ReadonlyArray<ApiItem> {
>members : readonly ApiItem[]
return [];
>[] : never[]
}
}
// Normal subclass
class ApiEnumMember extends ApiItem {
>ApiEnumMember : ApiEnumMember
>ApiItem : ApiItem
}
// Mixin base class
interface ApiItemContainerMixin extends ApiItem {
readonly members: ReadonlyArray<ApiItem>;
>members : readonly ApiItem[]
}
function ApiItemContainerMixin<TBaseClass extends IApiItemConstructor>(
>ApiItemContainerMixin : <TBaseClass extends IApiItemConstructor>(baseClass: TBaseClass) => TBaseClass & (new (...args: any[]) => ApiItemContainerMixin)
baseClass: TBaseClass
>baseClass : TBaseClass
): TBaseClass & (new (...args: any[]) => ApiItemContainerMixin) {
>args : any[]
abstract class MixedClass extends baseClass implements ApiItemContainerMixin {
>MixedClass : MixedClass
>baseClass : ApiItem
public constructor(...args: any[]) {
>args : any[]
super(...args);
>super(...args) : void
>super : TBaseClass
>...args : any
>args : any[]
}
public get members(): ReadonlyArray<ApiItem> {
>members : readonly ApiItem[]
return [];
>[] : never[]
}
}
return MixedClass;
>MixedClass : ((abstract new (...args: any[]) => MixedClass) & { prototype: ApiItemContainerMixin<any>.MixedClass; }) & TBaseClass
}
// Subclass inheriting from mixin
export class ApiEnum extends ApiItemContainerMixin(ApiItem) {
>ApiEnum : ApiEnum
>ApiItemContainerMixin(ApiItem) : ApiItem & ApiItemContainerMixin
>ApiItemContainerMixin : <TBaseClass extends IApiItemConstructor>(baseClass: TBaseClass) => TBaseClass & (new (...args: any[]) => ApiItemContainerMixin)
>ApiItem : typeof ApiItem
// This worked prior to TypeScript 4.0:
public get members(): ReadonlyArray<ApiEnumMember> {
>members : readonly ApiEnumMember[]
return [];
>[] : never[]
}
}
@@ -150,7 +150,7 @@ function f01(x: unknown) {
>undefined : undefined
>typeof x === "string" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {} | null
>"string" : "string"
x; // string | undefined
@@ -1,12 +1,23 @@
tests/cases/conformance/types/conditional/conditionalTypes1.ts(12,5): error TS2322: Type 'T' is not assignable to type 'NonNullable<T>'.
Type 'T' is not assignable to type '{}'.
tests/cases/conformance/types/conditional/conditionalTypes1.ts(17,5): error TS2322: Type 'T' is not assignable to type 'NonNullable<T>'.
Type 'string | undefined' is not assignable to type 'NonNullable<T>'.
Type 'undefined' is not assignable to type 'NonNullable<T>'.
Type 'undefined' is not assignable to type 'T'.
'undefined' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'string | undefined'.
Type 'T' is not assignable to type '{}'.
Type 'string | undefined' is not assignable to type '{}'.
Type 'undefined' is not assignable to type '{}'.
tests/cases/conformance/types/conditional/conditionalTypes1.ts(24,5): error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'NonNullable<Partial<T>[keyof T]>'.
Type 'undefined' is not assignable to type 'NonNullable<Partial<T>[keyof T]>'.
Type 'undefined' is not assignable to type 'T[keyof T] & {}'.
Type 'undefined' is not assignable to type 'T[keyof T]'.
tests/cases/conformance/types/conditional/conditionalTypes1.ts(29,5): error TS2322: Type 'T["x"]' is not assignable to type 'NonNullable<T["x"]>'.
Type 'string | undefined' is not assignable to type 'NonNullable<T["x"]>'.
Type 'undefined' is not assignable to type 'NonNullable<T["x"]>'.
Type 'undefined' is not assignable to type '{}'.
Type 'T["x"]' is not assignable to type '{}'.
Type 'string | undefined' is not assignable to type '{}'.
Type 'undefined' is not assignable to type '{}'.
tests/cases/conformance/types/conditional/conditionalTypes1.ts(103,5): error TS2322: Type 'FunctionProperties<T>' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to 'FunctionProperties<T>'.
tests/cases/conformance/types/conditional/conditionalTypes1.ts(104,5): error TS2322: Type 'NonFunctionProperties<T>' is not assignable to type 'T'.
@@ -72,6 +83,8 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(288,43): error TS
y = x; // Error
~
!!! error TS2322: Type 'T' is not assignable to type 'NonNullable<T>'.
!!! error TS2322: Type 'T' is not assignable to type '{}'.
!!! related TS2208 tests/cases/conformance/types/conditional/conditionalTypes1.ts:10:13: This type parameter probably needs an `extends object` constraint.
}
function f2<T extends string | undefined>(x: T, y: NonNullable<T>) {
@@ -81,6 +94,11 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(288,43): error TS
!!! error TS2322: Type 'T' is not assignable to type 'NonNullable<T>'.
!!! error TS2322: Type 'string | undefined' is not assignable to type 'NonNullable<T>'.
!!! error TS2322: Type 'undefined' is not assignable to type 'NonNullable<T>'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T'.
!!! error TS2322: 'undefined' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'string | undefined'.
!!! error TS2322: Type 'T' is not assignable to type '{}'.
!!! error TS2322: Type 'string | undefined' is not assignable to type '{}'.
!!! error TS2322: Type 'undefined' is not assignable to type '{}'.
let s1: string = x; // Error
let s2: string = y;
}
@@ -90,7 +108,8 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(288,43): error TS
y = x; // Error
~
!!! error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'NonNullable<Partial<T>[keyof T]>'.
!!! error TS2322: Type 'undefined' is not assignable to type 'NonNullable<Partial<T>[keyof T]>'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T] & {}'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T]'.
}
function f4<T extends { x: string | undefined }>(x: T["x"], y: NonNullable<T["x"]>) {
@@ -100,6 +119,10 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(288,43): error TS
!!! error TS2322: Type 'T["x"]' is not assignable to type 'NonNullable<T["x"]>'.
!!! error TS2322: Type 'string | undefined' is not assignable to type 'NonNullable<T["x"]>'.
!!! error TS2322: Type 'undefined' is not assignable to type 'NonNullable<T["x"]>'.
!!! error TS2322: Type 'undefined' is not assignable to type '{}'.
!!! error TS2322: Type 'T["x"]' is not assignable to type '{}'.
!!! error TS2322: Type 'string | undefined' is not assignable to type '{}'.
!!! error TS2322: Type 'undefined' is not assignable to type '{}'.
let s1: string = x; // Error
let s2: string = y;
}
@@ -55,7 +55,7 @@ function f2<T extends string | undefined>(x: T, y: NonNullable<T>) {
let s2: string = y;
>s2 : string
>y : NonNullable<T>
>y : string
}
function f3<T>(x: Partial<T>[keyof T], y: NonNullable<Partial<T>[keyof T]>) {
@@ -96,7 +96,7 @@ function f4<T extends { x: string | undefined }>(x: T["x"], y: NonNullable<T["x"
let s2: string = y;
>s2 : string
>y : NonNullable<T["x"]>
>y : string
}
type Options = { k: "a", a: number } | { k: "b", b: string } | { k: "c", c: boolean };
@@ -32,7 +32,7 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(74,12): error TS2
Property 'bat' is missing in type 'Foo & Bar' but required in type '{ foo: string; bat: string; }'.
tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2345: Argument of type 'Extract2<T, Foo, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
Type 'T extends Bar ? T : never' is not assignable to type '{ foo: string; bat: string; }'.
Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
Type 'Bar & Foo & T' is not assignable to type '{ foo: string; bat: string; }'.
==== tests/cases/conformance/types/conditional/conditionalTypes2.ts (7 errors) ====
@@ -155,8 +155,7 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
~
!!! error TS2345: Argument of type 'Extract2<T, Foo, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
!!! error TS2345: Type 'T extends Bar ? T : never' is not assignable to type '{ foo: string; bat: string; }'.
!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
!!! error TS2345: Type 'Bar & Foo & T' is not assignable to type '{ foo: string; bat: string; }'.
}
// Repros from #22860
@@ -10,7 +10,7 @@ function f1<T extends string | undefined>(x: T, y: { a: T }, z: [T]): string {
>x : T
x;
>x : T
>x : NonNullable<T>
x.length;
>x.length : number
@@ -67,7 +67,7 @@ function f2<T>(x: Extract<T, string | undefined> | null): string {
>x : Extract<T, string | undefined> | null
x;
>x : Extract<T, string | undefined>
>x : NonNullable<Extract<T, string | undefined>>
x.length;
>x.length : number
@@ -404,11 +404,11 @@ function fx1<T, K extends keyof T>(obj: T, key: K) {
>key : K
const x2 = obj && obj[key];
>x2 : T[K]
>obj && obj[key] : T[K]
>obj : T
>obj[key] : T[K]
>x2 : NonNullable<T>[K]
>obj && obj[key] : NonNullable<T>[K]
>obj : T
>obj[key] : NonNullable<T>[K]
>obj : NonNullable<T>
>key : K
}
@@ -438,8 +438,8 @@ function fx3<T extends Record<keyof T, string> | undefined, K extends keyof T>(o
>key : K
const x1 = obj[key]; // Error
>x1 : NonNullable<Record<keyof T, string>>[K]
>obj[key] : NonNullable<Record<keyof T, string>>[K]
>x1 : Record<keyof T, string>[K]
>obj[key] : Record<keyof T, string>[K]
>obj : Record<keyof T, string> | undefined
>key : K
@@ -469,14 +469,14 @@ class TableBaseEnum<
>null : null
iSpec[null! as keyof InternalSpec]; // Error, object possibly undefined
>iSpec[null! as keyof InternalSpec] : NonNullable<Record<keyof PublicSpec, any>>[keyof InternalSpec]
>iSpec[null! as keyof InternalSpec] : Record<keyof PublicSpec, any>[keyof InternalSpec]
>iSpec : Record<keyof PublicSpec, any> | undefined
>null! as keyof InternalSpec : keyof InternalSpec
>null! : never
>null : null
iSpec[null! as keyof PublicSpec]; // Error, object possibly undefined
>iSpec[null! as keyof PublicSpec] : NonNullable<Record<keyof PublicSpec, any>>[keyof PublicSpec]
>iSpec[null! as keyof PublicSpec] : Record<keyof PublicSpec, any>[keyof PublicSpec]
>iSpec : Record<keyof PublicSpec, any> | undefined
>null! as keyof PublicSpec : keyof PublicSpec
>null! : never
@@ -181,7 +181,7 @@ function f8<T>(x: T) {
>x : T
x; // {}
>x : T
>x : NonNullable<T>
}
else {
x; // {}
@@ -16,7 +16,7 @@ function f1(x: unknown) {
if (typeof x === 'object') {
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {}
>'object' : "object"
obj(x);
@@ -40,7 +40,7 @@ function f2(x: unknown) {
if (typeof x === 'object') {
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {} | undefined
>'object' : "object"
obj(x);
@@ -64,7 +64,7 @@ function f3(x: unknown) {
if (typeof x === 'object') {
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {}
>'object' : "object"
obj(x);
@@ -88,7 +88,7 @@ function f4(x: unknown) {
if (typeof x === 'object') {
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {}
>'object' : "object"
obj(x);
@@ -126,7 +126,7 @@ function f5(x: unknown) {
if (typeof x === 'object') {
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {} | undefined
>'object' : "object"
obj(x);
@@ -150,12 +150,12 @@ function f6(x: unknown) {
}
else {
x;
>x : unknown
>x : {} | undefined
if (typeof x === 'object') {
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {} | undefined
>'object' : "object"
obj(x);
@@ -0,0 +1,25 @@
tests/cases/compiler/b.ts(2,14): error TS4118: The type of this node cannot be serialized because its property '[timestampSymbol]' cannot be serialized.
tests/cases/compiler/c.ts(3,14): error TS4118: The type of this node cannot be serialized because its property '[timestampSymbol]' cannot be serialized.
==== tests/cases/compiler/a.d.ts (0 errors) ====
export declare const timestampSymbol: unique symbol;
export declare const Timestamp: {
[TKey in typeof timestampSymbol]: true;
};
export declare function now(): typeof Timestamp;
==== tests/cases/compiler/b.ts (1 errors) ====
import * as x from "./a";
export const timestamp = x.now();
~~~~~~~~~
!!! error TS4118: The type of this node cannot be serialized because its property '[timestampSymbol]' cannot be serialized.
==== tests/cases/compiler/c.ts (1 errors) ====
import { now } from "./a";
export const timestamp = now();
~~~~~~~~~
!!! error TS4118: The type of this node cannot be serialized because its property '[timestampSymbol]' cannot be serialized.
@@ -0,0 +1,32 @@
//// [tests/cases/compiler/declarationEmitMappedTypeTemplateTypeofSymbol.ts] ////
//// [a.d.ts]
export declare const timestampSymbol: unique symbol;
export declare const Timestamp: {
[TKey in typeof timestampSymbol]: true;
};
export declare function now(): typeof Timestamp;
//// [b.ts]
import * as x from "./a";
export const timestamp = x.now();
//// [c.ts]
import { now } from "./a";
export const timestamp = now();
//// [b.js]
"use strict";
exports.__esModule = true;
exports.timestamp = void 0;
var x = require("./a");
exports.timestamp = x.now();
//// [c.js]
"use strict";
exports.__esModule = true;
exports.timestamp = void 0;
var a_1 = require("./a");
exports.timestamp = (0, a_1.now)();
@@ -0,0 +1,35 @@
=== tests/cases/compiler/a.d.ts ===
export declare const timestampSymbol: unique symbol;
>timestampSymbol : Symbol(timestampSymbol, Decl(a.d.ts, 0, 20))
export declare const Timestamp: {
>Timestamp : Symbol(Timestamp, Decl(a.d.ts, 2, 20))
[TKey in typeof timestampSymbol]: true;
>TKey : Symbol(TKey, Decl(a.d.ts, 3, 5))
>timestampSymbol : Symbol(timestampSymbol, Decl(a.d.ts, 0, 20))
};
export declare function now(): typeof Timestamp;
>now : Symbol(now, Decl(a.d.ts, 4, 2))
>Timestamp : Symbol(Timestamp, Decl(a.d.ts, 2, 20))
=== tests/cases/compiler/b.ts ===
import * as x from "./a";
>x : Symbol(x, Decl(b.ts, 0, 6))
export const timestamp = x.now();
>timestamp : Symbol(timestamp, Decl(b.ts, 1, 12))
>x.now : Symbol(x.now, Decl(a.d.ts, 4, 2))
>x : Symbol(x, Decl(b.ts, 0, 6))
>now : Symbol(x.now, Decl(a.d.ts, 4, 2))
=== tests/cases/compiler/c.ts ===
import { now } from "./a";
>now : Symbol(now, Decl(c.ts, 0, 8))
export const timestamp = now();
>timestamp : Symbol(timestamp, Decl(c.ts, 2, 12))
>now : Symbol(now, Decl(c.ts, 0, 8))
@@ -0,0 +1,37 @@
=== tests/cases/compiler/a.d.ts ===
export declare const timestampSymbol: unique symbol;
>timestampSymbol : unique symbol
export declare const Timestamp: {
>Timestamp : { [timestampSymbol]: true; }
[TKey in typeof timestampSymbol]: true;
>timestampSymbol : unique symbol
>true : true
};
export declare function now(): typeof Timestamp;
>now : () => typeof Timestamp
>Timestamp : { [timestampSymbol]: true; }
=== tests/cases/compiler/b.ts ===
import * as x from "./a";
>x : typeof x
export const timestamp = x.now();
>timestamp : { [x.timestampSymbol]: true; }
>x.now() : { [x.timestampSymbol]: true; }
>x.now : () => { [x.timestampSymbol]: true; }
>x : typeof x
>now : () => { [x.timestampSymbol]: true; }
=== tests/cases/compiler/c.ts ===
import { now } from "./a";
>now : () => { [timestampSymbol]: true; }
export const timestamp = now();
>timestamp : { [timestampSymbol]: true; }
>now() : { [timestampSymbol]: true; }
>now : () => { [timestampSymbol]: true; }
@@ -14,8 +14,8 @@ function Menu<MenuItemVariant extends ListItemVariant = ListItemVariant.OneLine>
>data : IData<MenuItemVariant>
const listItemVariant = data.menuItemsVariant ?? ListItemVariant.OneLine;
>listItemVariant : ListItemVariant.OneLine | NonNullable<MenuItemVariant>
>data.menuItemsVariant ?? ListItemVariant.OneLine : ListItemVariant.OneLine | NonNullable<MenuItemVariant>
>listItemVariant : ListItemVariant.OneLine | MenuItemVariant
>data.menuItemsVariant ?? ListItemVariant.OneLine : ListItemVariant.OneLine | MenuItemVariant
>data.menuItemsVariant : MenuItemVariant | undefined
>data : IData<MenuItemVariant>
>menuItemsVariant : MenuItemVariant | undefined
@@ -1,4 +1,4 @@
tests/cases/compiler/errorLocationForInterfaceExtension.ts(3,21): error TS2693: 'string' only refers to a type, but is being used as a value here.
tests/cases/compiler/errorLocationForInterfaceExtension.ts(3,21): error TS2840: An interface cannot extend a primitive type like 'string'; an interface can only extend named types and classes
==== tests/cases/compiler/errorLocationForInterfaceExtension.ts (1 errors) ====
@@ -6,5 +6,5 @@ tests/cases/compiler/errorLocationForInterfaceExtension.ts(3,21): error TS2693:
interface x extends string { }
~~~~~~
!!! error TS2693: 'string' only refers to a type, but is being used as a value here.
!!! error TS2840: An interface cannot extend a primitive type like 'string'; an interface can only extend named types and classes
@@ -89,7 +89,7 @@
"containerName": "",
"fileName": "/tests/cases/fourslash/findAllRefsRootSymbols.ts",
"kind": "property",
"name": "(property) x: {} & string",
"name": "(property) x: string",
"textSpan": {
"start": 14,
"length": 1
@@ -123,26 +123,6 @@
"text": " ",
"kind": "space"
},
{
"text": "{",
"kind": "punctuation"
},
{
"text": "}",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "&",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "string",
"kind": "keyword"
@@ -258,7 +238,7 @@
"containerName": "",
"fileName": "/tests/cases/fourslash/findAllRefsRootSymbols.ts",
"kind": "property",
"name": "(property) x: {} & string",
"name": "(property) x: string",
"textSpan": {
"start": 14,
"length": 1
@@ -292,26 +272,6 @@
"text": " ",
"kind": "space"
},
{
"text": "{",
"kind": "punctuation"
},
{
"text": "}",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "&",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "string",
"kind": "keyword"
@@ -415,7 +375,7 @@
"containerName": "",
"fileName": "/tests/cases/fourslash/findAllRefsRootSymbols.ts",
"kind": "property",
"name": "(property) x: {} & string",
"name": "(property) x: string",
"textSpan": {
"start": 14,
"length": 1
@@ -449,26 +409,6 @@
"text": " ",
"kind": "space"
},
{
"text": "{",
"kind": "punctuation"
},
{
"text": "}",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "&",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "string",
"kind": "keyword"
@@ -725,7 +665,7 @@
"containerName": "",
"fileName": "/tests/cases/fourslash/findAllRefsRootSymbols.ts",
"kind": "property",
"name": "(property) x: {} & string",
"name": "(property) x: string",
"textSpan": {
"start": 14,
"length": 1
@@ -759,26 +699,6 @@
"text": " ",
"kind": "space"
},
{
"text": "{",
"kind": "punctuation"
},
{
"text": "}",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "&",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "string",
"kind": "keyword"
@@ -1,8 +1,10 @@
tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(2,5): error TS2339: Property 'toString' does not exist on type 'T'.
tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(15,6): error TS2345: Argument of type 'T' is not assignable to parameter of type '{}'.
tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(16,6): error TS2345: Argument of type 'T' is not assignable to parameter of type 'Record<string, any>'.
tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(17,5): error TS2339: Property 'toString' does not exist on type 'T'.
==== tests/cases/compiler/genericUnboundedTypeParamAssignability.ts (2 errors) ====
==== tests/cases/compiler/genericUnboundedTypeParamAssignability.ts (4 errors) ====
function f1<T>(o: T) {
o.toString(); // error
~~~~~~~~
@@ -20,7 +22,13 @@ tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(17,5): error TS23
function user<T>(t: T) {
f1(t);
f2(t); // error in strict, unbounded T doesn't satisfy the constraint
~
!!! error TS2345: Argument of type 'T' is not assignable to parameter of type '{}'.
!!! related TS2208 tests/cases/compiler/genericUnboundedTypeParamAssignability.ts:13:15: This type parameter probably needs an `extends object` constraint.
f3(t); // error in strict, unbounded T doesn't satisfy the constraint
~
!!! error TS2345: Argument of type 'T' is not assignable to parameter of type 'Record<string, any>'.
!!! related TS2208 tests/cases/compiler/genericUnboundedTypeParamAssignability.ts:13:15: This type parameter probably needs an `extends object` constraint.
t.toString(); // error, for the same reason as f1()
~~~~~~~~
!!! error TS2339: Property 'toString' does not exist on type 'T'.
@@ -3,12 +3,11 @@ tests/cases/compiler/inDoesNotOperateOnPrimitiveTypes.ts(23,12): error TS2361: T
tests/cases/compiler/inDoesNotOperateOnPrimitiveTypes.ts(27,12): error TS2361: The right-hand side of an 'in' expression must not be a primitive.
tests/cases/compiler/inDoesNotOperateOnPrimitiveTypes.ts(34,12): error TS2361: The right-hand side of an 'in' expression must not be a primitive.
tests/cases/compiler/inDoesNotOperateOnPrimitiveTypes.ts(53,14): error TS2361: The right-hand side of an 'in' expression must not be a primitive.
tests/cases/compiler/inDoesNotOperateOnPrimitiveTypes.ts(55,18): error TS2361: The right-hand side of an 'in' expression must not be a primitive.
tests/cases/compiler/inDoesNotOperateOnPrimitiveTypes.ts(60,12): error TS2361: The right-hand side of an 'in' expression must not be a primitive.
tests/cases/compiler/inDoesNotOperateOnPrimitiveTypes.ts(64,12): error TS2361: The right-hand side of an 'in' expression must not be a primitive.
==== tests/cases/compiler/inDoesNotOperateOnPrimitiveTypes.ts (8 errors) ====
==== tests/cases/compiler/inDoesNotOperateOnPrimitiveTypes.ts (7 errors) ====
const validHasKey = <T extends object>(
thing: T,
key: string,
@@ -74,8 +73,6 @@ tests/cases/compiler/inDoesNotOperateOnPrimitiveTypes.ts(64,12): error TS2361: T
!!! error TS2361: The right-hand side of an 'in' expression must not be a primitive.
if (typeof p === "object") {
"key" in p;
~
!!! error TS2361: The right-hand side of an 'in' expression must not be a primitive.
}
}
@@ -146,7 +146,7 @@ function union5<T extends object | string, U extends object | number>(p: T | U)
"key" in p;
>"key" in p : boolean
>"key" : "key"
>p : T | U
>p : (T & object) | (U & object)
}
}
@@ -3,9 +3,11 @@ tests/cases/compiler/interfacedeclWithIndexerErrors.ts(14,5): error TS2411: Prop
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(15,5): error TS2411: Property 'p5' of type '(s: number) => string' is not assignable to 'string' index type '() => string'.
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(19,5): error TS2411: Property 'f3' of type '(a: string) => number' is not assignable to 'string' index type '() => string'.
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(20,5): error TS2411: Property 'f4' of type '(s: number) => string' is not assignable to 'string' index type '() => string'.
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(44,21): error TS2840: An interface cannot extend a primitive type like 'number'; an interface can only extend named types and classes
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(48,18): error TS2693: 'string' only refers to a type, but is being used as a value here.
==== tests/cases/compiler/interfacedeclWithIndexerErrors.ts (5 errors) ====
==== tests/cases/compiler/interfacedeclWithIndexerErrors.ts (7 errors) ====
interface a0 {
(): string;
(a, b, c?: string): number;
@@ -59,6 +61,17 @@ tests/cases/compiler/interfacedeclWithIndexerErrors.ts(20,5): error TS2411: Prop
interface d extends a {
}
interface e extends number {
~~~~~~
!!! error TS2840: An interface cannot extend a primitive type like 'number'; an interface can only extend named types and classes
}
interface f {
prop: typeof string;
~~~~~~
!!! error TS2693: 'string' only refers to a type, but is being used as a value here.
}
class c1 implements a {
}
var instance2 = new c1();
@@ -42,6 +42,13 @@ interface c extends a, b {
interface d extends a {
}
interface e extends number {
}
interface f {
prop: typeof string;
}
class c1 implements a {
}
var instance2 = new c1();
@@ -84,11 +84,22 @@ interface d extends a {
>a : Symbol(a, Decl(interfacedeclWithIndexerErrors.ts, 29, 1))
}
interface e extends number {
>e : Symbol(e, Decl(interfacedeclWithIndexerErrors.ts, 41, 1))
}
interface f {
>f : Symbol(f, Decl(interfacedeclWithIndexerErrors.ts, 44, 1))
prop: typeof string;
>prop : Symbol(f.prop, Decl(interfacedeclWithIndexerErrors.ts, 46, 13))
}
class c1 implements a {
>c1 : Symbol(c1, Decl(interfacedeclWithIndexerErrors.ts, 41, 1))
>c1 : Symbol(c1, Decl(interfacedeclWithIndexerErrors.ts, 48, 1))
>a : Symbol(a, Decl(interfacedeclWithIndexerErrors.ts, 29, 1))
}
var instance2 = new c1();
>instance2 : Symbol(instance2, Decl(interfacedeclWithIndexerErrors.ts, 45, 3))
>c1 : Symbol(c1, Decl(interfacedeclWithIndexerErrors.ts, 41, 1))
>instance2 : Symbol(instance2, Decl(interfacedeclWithIndexerErrors.ts, 52, 3))
>c1 : Symbol(c1, Decl(interfacedeclWithIndexerErrors.ts, 48, 1))
@@ -70,6 +70,15 @@ interface c extends a, b {
interface d extends a {
}
interface e extends number {
}
interface f {
prop: typeof string;
>prop : any
>string : any
}
class c1 implements a {
>c1 : c1
}
@@ -346,7 +346,7 @@ function inGeneric<T extends A2 | B2>(alsoShouldBeB: T & B2) {
const b: B2 = alsoShouldBeB;
>b : B2
>alsoShouldBeB : T & B2
>alsoShouldBeB : B2
}
// Repro from #38542
@@ -374,6 +374,6 @@ function bar<T extends CA | CB>(x: T & CA) {
let ab: ABI = x;
>ab : ABI
>x : T & CA
>x : CA
}
@@ -1,8 +1,13 @@
tests/cases/conformance/types/intersection/intersectionWithUnionConstraint.ts(7,9): error TS2322: Type 'T & U' is not assignable to type 'string | number'.
tests/cases/conformance/types/intersection/intersectionWithUnionConstraint.ts(8,9): error TS2322: Type 'T & U' is not assignable to type 'string | null'.
tests/cases/conformance/types/intersection/intersectionWithUnionConstraint.ts(10,9): error TS2322: Type 'T & U' is not assignable to type 'number | null'.
tests/cases/conformance/types/intersection/intersectionWithUnionConstraint.ts(11,9): error TS2322: Type 'T & U' is not assignable to type 'number | undefined'.
tests/cases/conformance/types/intersection/intersectionWithUnionConstraint.ts(12,9): error TS2322: Type 'T & U' is not assignable to type 'null | undefined'.
tests/cases/conformance/types/intersection/intersectionWithUnionConstraint.ts(7,9): error TS2322: Type 'string | undefined' is not assignable to type 'string | number'.
Type 'undefined' is not assignable to type 'string | number'.
tests/cases/conformance/types/intersection/intersectionWithUnionConstraint.ts(8,9): error TS2322: Type 'string | undefined' is not assignable to type 'string | null'.
Type 'undefined' is not assignable to type 'string | null'.
tests/cases/conformance/types/intersection/intersectionWithUnionConstraint.ts(10,9): error TS2322: Type 'string | undefined' is not assignable to type 'number | null'.
Type 'undefined' is not assignable to type 'number | null'.
tests/cases/conformance/types/intersection/intersectionWithUnionConstraint.ts(11,9): error TS2322: Type 'string | undefined' is not assignable to type 'number | undefined'.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/intersection/intersectionWithUnionConstraint.ts(12,9): error TS2322: Type 'string | undefined' is not assignable to type 'null | undefined'.
Type 'string' is not assignable to type 'null | undefined'.
==== tests/cases/conformance/types/intersection/intersectionWithUnionConstraint.ts (5 errors) ====
@@ -14,20 +19,25 @@ tests/cases/conformance/types/intersection/intersectionWithUnionConstraint.ts(12
function f2<T extends string | number | undefined, U extends string | null | undefined>(x: T & U) {
let y1: string | number = x; // Error
~~
!!! error TS2322: Type 'T & U' is not assignable to type 'string | number'.
!!! error TS2322: Type 'string | undefined' is not assignable to type 'string | number'.
!!! error TS2322: Type 'undefined' is not assignable to type 'string | number'.
let y2: string | null = x; // Error
~~
!!! error TS2322: Type 'T & U' is not assignable to type 'string | null'.
!!! error TS2322: Type 'string | undefined' is not assignable to type 'string | null'.
!!! error TS2322: Type 'undefined' is not assignable to type 'string | null'.
let y3: string | undefined = x;
let y4: number | null = x; // Error
~~
!!! error TS2322: Type 'T & U' is not assignable to type 'number | null'.
!!! error TS2322: Type 'string | undefined' is not assignable to type 'number | null'.
!!! error TS2322: Type 'undefined' is not assignable to type 'number | null'.
let y5: number | undefined = x; // Error
~~
!!! error TS2322: Type 'T & U' is not assignable to type 'number | undefined'.
!!! error TS2322: Type 'string | undefined' is not assignable to type 'number | undefined'.
!!! error TS2322: Type 'string' is not assignable to type 'number'.
let y6: null | undefined = x; // Error
~~
!!! error TS2322: Type 'T & U' is not assignable to type 'null | undefined'.
!!! error TS2322: Type 'string | undefined' is not assignable to type 'null | undefined'.
!!! error TS2322: Type 'string' is not assignable to type 'null | undefined'.
}
type T1 = (string | number | undefined) & (string | null | undefined); // string | undefined
@@ -6,7 +6,7 @@ function f1<T extends string | number, U extends string | number>(x: T & U) {
// Combined constraint of 'T & U' is 'string | number'
let y: string | number = x;
>y : string | number
>x : T & U
>x : string | number
}
function f2<T extends string | number | undefined, U extends string | null | undefined>(x: T & U) {
@@ -16,30 +16,30 @@ function f2<T extends string | number | undefined, U extends string | null | und
let y1: string | number = x; // Error
>y1 : string | number
>x : T & U
>x : string | undefined
let y2: string | null = x; // Error
>y2 : string | null
>null : null
>x : T & U
>x : string | undefined
let y3: string | undefined = x;
>y3 : string | undefined
>x : T & U
>x : string | undefined
let y4: number | null = x; // Error
>y4 : number | null
>null : null
>x : T & U
>x : string | undefined
let y5: number | undefined = x; // Error
>y5 : number | undefined
>x : T & U
>x : string | undefined
let y6: null | undefined = x; // Error
>y6 : null | undefined
>null : null
>x : T & U
>x : string | undefined
}
type T1 = (string | number | undefined) & (string | null | undefined); // string | undefined
@@ -52,7 +52,7 @@ function f3<T extends string | number | undefined>(x: T & (number | object | und
const y: number | undefined = x;
>y : number | undefined
>x : T & (number | object | undefined)
>x : number | undefined
}
function f4<T extends string | number>(x: T & (number | object)) {
@@ -61,7 +61,7 @@ function f4<T extends string | number>(x: T & (number | object)) {
const y: number = x;
>y : number
>x : T & (number | object)
>x : number
}
function f5<T, U extends keyof T>(x: keyof T & U) {
@@ -70,7 +70,7 @@ function f5<T, U extends keyof T>(x: keyof T & U) {
let y: keyof any = x;
>y : string | number | symbol
>x : keyof T & U
>x : string | number | symbol
}
// Repro from #23648
@@ -26,10 +26,10 @@ let x04: A & B & C;
>x04 : A & B
let x05: string & C;
>x05 : string & C
>x05 : string
let x06: C & string;
>x06 : C & string
>x06 : string
let x07: C;
>x07 : C
@@ -0,0 +1,677 @@
tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts(316,5): error TS2322: Type 'T' is not assignable to type '{}'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts(317,5): error TS2322: Type 'T[keyof T]' is not assignable to type '{}'.
Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{}'.
Type 'T[string]' is not assignable to type '{}'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts(318,5): error TS2322: Type 'T[K]' is not assignable to type '{}'.
Type 'T[keyof T]' is not assignable to type '{}'.
==== tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts (3 errors) ====
class Shape {
name: string;
width: number;
height: number;
visible: boolean;
}
class TaggedShape extends Shape {
tag: string;
}
class Item {
name: string;
price: number;
}
class Options {
visible: "yes" | "no";
}
type Dictionary<T> = { [x: string]: T };
type NumericallyIndexed<T> = { [x: number]: T };
const enum E { A, B, C }
type K00 = keyof any; // string
type K01 = keyof string; // "toString" | "charAt" | ...
type K02 = keyof number; // "toString" | "toFixed" | "toExponential" | ...
type K03 = keyof boolean; // "valueOf"
type K04 = keyof void; // never
type K05 = keyof undefined; // never
type K06 = keyof null; // never
type K07 = keyof never; // string | number | symbol
type K08 = keyof unknown; // never
type K10 = keyof Shape; // "name" | "width" | "height" | "visible"
type K11 = keyof Shape[]; // "length" | "toString" | ...
type K12 = keyof Dictionary<Shape>; // string
type K13 = keyof {}; // never
type K14 = keyof Object; // "constructor" | "toString" | ...
type K15 = keyof E; // "toString" | "toFixed" | "toExponential" | ...
type K16 = keyof [string, number]; // "0" | "1" | "length" | "toString" | ...
type K17 = keyof (Shape | Item); // "name"
type K18 = keyof (Shape & Item); // "name" | "width" | "height" | "visible" | "price"
type K19 = keyof NumericallyIndexed<Shape> // never
type KeyOf<T> = keyof T;
type K20 = KeyOf<Shape>; // "name" | "width" | "height" | "visible"
type K21 = KeyOf<Dictionary<Shape>>; // string
type NAME = "name";
type WIDTH_OR_HEIGHT = "width" | "height";
type Q10 = Shape["name"]; // string
type Q11 = Shape["width" | "height"]; // number
type Q12 = Shape["name" | "visible"]; // string | boolean
type Q20 = Shape[NAME]; // string
type Q21 = Shape[WIDTH_OR_HEIGHT]; // number
type Q30 = [string, number][0]; // string
type Q31 = [string, number][1]; // number
type Q32 = [string, number][number]; // string | number
type Q33 = [string, number][E.A]; // string
type Q34 = [string, number][E.B]; // number
type Q35 = [string, number]["0"]; // string
type Q36 = [string, number]["1"]; // string
type Q40 = (Shape | Options)["visible"]; // boolean | "yes" | "no"
type Q41 = (Shape & Options)["visible"]; // true & "yes" | true & "no" | false & "yes" | false & "no"
type Q50 = Dictionary<Shape>["howdy"]; // Shape
type Q51 = Dictionary<Shape>[123]; // Shape
type Q52 = Dictionary<Shape>[E.B]; // Shape
declare let cond: boolean;
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) {
obj[key] = value;
}
function f10(shape: Shape) {
let name = getProperty(shape, "name"); // string
let widthOrHeight = getProperty(shape, cond ? "width" : "height"); // number
let nameOrVisible = getProperty(shape, cond ? "name" : "visible"); // string | boolean
setProperty(shape, "name", "rectangle");
setProperty(shape, cond ? "width" : "height", 10);
setProperty(shape, cond ? "name" : "visible", true); // Technically not safe
}
function f11(a: Shape[]) {
let len = getProperty(a, "length"); // number
setProperty(a, "length", len);
}
function f12(t: [Shape, boolean]) {
let len = getProperty(t, "length");
let s2 = getProperty(t, "0"); // Shape
let b2 = getProperty(t, "1"); // boolean
}
function f13(foo: any, bar: any) {
let x = getProperty(foo, "x"); // any
let y = getProperty(foo, "100"); // any
let z = getProperty(foo, bar); // any
}
class Component<PropType> {
props: PropType;
getProperty<K extends keyof PropType>(key: K) {
return this.props[key];
}
setProperty<K extends keyof PropType>(key: K, value: PropType[K]) {
this.props[key] = value;
}
}
function f20(component: Component<Shape>) {
let name = component.getProperty("name"); // string
let widthOrHeight = component.getProperty(cond ? "width" : "height"); // number
let nameOrVisible = component.getProperty(cond ? "name" : "visible"); // string | boolean
component.setProperty("name", "rectangle");
component.setProperty(cond ? "width" : "height", 10)
component.setProperty(cond ? "name" : "visible", true); // Technically not safe
}
function pluck<T, K extends keyof T>(array: T[], key: K) {
return array.map(x => x[key]);
}
function f30(shapes: Shape[]) {
let names = pluck(shapes, "name"); // string[]
let widths = pluck(shapes, "width"); // number[]
let nameOrVisibles = pluck(shapes, cond ? "name" : "visible"); // (string | boolean)[]
}
function f31<K extends keyof Shape>(key: K) {
const shape: Shape = { name: "foo", width: 5, height: 10, visible: true };
return shape[key]; // Shape[K]
}
function f32<K extends "width" | "height">(key: K) {
const shape: Shape = { name: "foo", width: 5, height: 10, visible: true };
return shape[key]; // Shape[K]
}
function f33<S extends Shape, K extends keyof S>(shape: S, key: K) {
let name = getProperty(shape, "name");
let prop = getProperty(shape, key);
return prop;
}
function f34(ts: TaggedShape) {
let tag1 = f33(ts, "tag");
let tag2 = getProperty(ts, "tag");
}
class C {
public x: string;
protected y: string;
private z: string;
}
// Indexed access expressions have always permitted access to private and protected members.
// For consistency we also permit such access in indexed access types.
function f40(c: C) {
type X = C["x"];
type Y = C["y"];
type Z = C["z"];
let x: X = c["x"];
let y: Y = c["y"];
let z: Z = c["z"];
}
function f50<T>(k: keyof T, s: string) {
const x1 = s as keyof T;
const x2 = k as string;
}
function f51<T, K extends keyof T>(k: K, s: string) {
const x1 = s as keyof T;
const x2 = k as string;
}
function f52<T>(obj: { [x: string]: boolean }, k: Exclude<keyof T, symbol>, s: string, n: number) {
const x1 = obj[s];
const x2 = obj[n];
const x3 = obj[k];
}
function f53<T, K extends Exclude<keyof T, symbol>>(obj: { [x: string]: boolean }, k: K, s: string, n: number) {
const x1 = obj[s];
const x2 = obj[n];
const x3 = obj[k];
}
function f54<T>(obj: T, key: keyof T) {
for (let s in obj[key]) {
}
const b = "foo" in obj[key];
}
function f55<T, K extends keyof T>(obj: T, key: K) {
for (let s in obj[key]) {
}
const b = "foo" in obj[key];
}
function f60<T>(source: T, target: T) {
for (let k in source) {
target[k] = source[k];
}
}
function f70(func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void) {
func<{ a: any, b: any }, { a: any, c: any }>('a', 'a');
func<{ a: any, b: any }, { a: any, c: any }>('a', 'b');
func<{ a: any, b: any }, { a: any, c: any }>('a', 'c');
}
function f71(func: <T, U>(x: T, y: U) => Partial<T & U>) {
let x = func({ a: 1, b: "hello" }, { c: true });
x.a; // number | undefined
x.b; // string | undefined
x.c; // boolean | undefined
}
function f72(func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]) {
let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
}
function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]) {
let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
}
function f74(func: <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]) {
let a = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a'); // number
let b = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b'); // string | boolean
}
function f80<T extends { a: { x: any } }>(obj: T) {
let a1 = obj.a; // { x: any }
let a2 = obj['a']; // { x: any }
let a3 = obj['a'] as T['a']; // T["a"]
let x1 = obj.a.x; // any
let x2 = obj['a']['x']; // any
let x3 = obj['a']['x'] as T['a']['x']; // T["a"]["x"]
}
function f81<T extends { a: { x: any } }>(obj: T) {
return obj['a']['x'] as T['a']['x'];
}
function f82() {
let x1 = f81({ a: { x: "hello" } }); // string
let x2 = f81({ a: { x: 42 } }); // number
}
function f83<T extends { [x: string]: { x: any } }, K extends keyof T>(obj: T, key: K) {
return obj[key]['x'] as T[K]['x'];
}
function f84() {
let x1 = f83({ foo: { x: "hello" } }, "foo"); // string
let x2 = f83({ bar: { x: 42 } }, "bar"); // number
}
class C1 {
x: number;
get<K extends keyof this>(key: K) {
return this[key];
}
set<K extends keyof this>(key: K, value: this[K]) {
this[key] = value;
}
foo() {
let x1 = this.x; // number
let x2 = this["x"]; // number
let x3 = this.get("x"); // this["x"]
let x4 = getProperty(this, "x"); // this["x"]
this.x = 42;
this["x"] = 42;
this.set("x", 42);
setProperty(this, "x", 42);
}
}
type S2 = {
a: string;
b: string;
};
function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K]) {
x1 = x2;
x1 = x3;
x2 = x1;
x2 = x3;
x3 = x1;
x3 = x2;
x1.length;
x2.length;
x3.length;
}
function f91<T, K extends keyof T>(x: T, y: T[keyof T], z: T[K]) {
let a: {};
a = x;
~
!!! error TS2322: Type 'T' is not assignable to type '{}'.
!!! related TS2208 tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts:314:14: This type parameter probably needs an `extends object` constraint.
a = y;
~
!!! error TS2322: Type 'T[keyof T]' is not assignable to type '{}'.
!!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{}'.
!!! error TS2322: Type 'T[string]' is not assignable to type '{}'.
a = z;
~
!!! error TS2322: Type 'T[K]' is not assignable to type '{}'.
!!! error TS2322: Type 'T[keyof T]' is not assignable to type '{}'.
}
function f92<T, K extends keyof T>(x: T, y: T[keyof T], z: T[K]) {
let a: {} | null | undefined;
a = x;
a = y;
a = z;
}
// Repros from #12011
class Base {
get<K extends keyof this>(prop: K) {
return this[prop];
}
set<K extends keyof this>(prop: K, value: this[K]) {
this[prop] = value;
}
}
class Person extends Base {
parts: number;
constructor(parts: number) {
super();
this.set("parts", parts);
}
getParts() {
return this.get("parts")
}
}
class OtherPerson {
parts: number;
constructor(parts: number) {
setProperty(this, "parts", parts);
}
getParts() {
return getProperty(this, "parts")
}
}
// Modified repro from #12544
function path<T, K1 extends keyof T>(obj: T, key1: K1): T[K1];
function path<T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2];
function path<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
function path(obj: any, ...keys: (string | number)[]): any;
function path(obj: any, ...keys: (string | number)[]): any {
let result = obj;
for (let k of keys) {
result = result[k];
}
return result;
}
type Thing = {
a: { x: number, y: string },
b: boolean
};
function f1(thing: Thing) {
let x1 = path(thing, 'a'); // { x: number, y: string }
let x2 = path(thing, 'a', 'y'); // string
let x3 = path(thing, 'b'); // boolean
let x4 = path(thing, ...['a', 'x']); // any
}
// Repro from comment in #12114
const assignTo2 = <T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) =>
(value: T[K1][K2]) => object[key1][key2] = value;
// Modified repro from #12573
declare function one<T>(handler: (t: T) => void): T
var empty = one(() => {}) // inferred as {}, expected
type Handlers<T> = { [K in keyof T]: (t: T[K]) => void }
declare function on<T>(handlerHash: Handlers<T>): T
var hashOfEmpty1 = on({ test: () => {} }); // {}
var hashOfEmpty2 = on({ test: (x: boolean) => {} }); // { test: boolean }
// Repro from #12624
interface Options1<Data, Computed> {
data?: Data
computed?: Computed;
}
declare class Component1<Data, Computed> {
constructor(options: Options1<Data, Computed>);
get<K extends keyof (Data & Computed)>(key: K): (Data & Computed)[K];
}
let c1 = new Component1({
data: {
hello: ""
}
});
c1.get("hello");
// Repro from #12625
interface Options2<Data, Computed> {
data?: Data
computed?: Computed;
}
declare class Component2<Data, Computed> {
constructor(options: Options2<Data, Computed>);
get<K extends keyof Data | keyof Computed>(key: K): (Data & Computed)[K];
}
// Repro from #12641
interface R {
p: number;
}
function f<K extends keyof R>(p: K) {
let a: any;
a[p].add; // any
}
// Repro from #12651
type MethodDescriptor = {
name: string;
args: any[];
returnValue: any;
}
declare function dispatchMethod<M extends MethodDescriptor>(name: M['name'], args: M['args']): M['returnValue'];
type SomeMethodDescriptor = {
name: "someMethod";
args: [string, number];
returnValue: string[];
}
let result = dispatchMethod<SomeMethodDescriptor>("someMethod", ["hello", 35]);
// Repro from #13073
type KeyTypes = "a" | "b"
let MyThingy: { [key in KeyTypes]: string[] };
function addToMyThingy<S extends KeyTypes>(key: S) {
MyThingy[key].push("a");
}
// Repro from #13102
type Handler<T> = {
onChange: (name: keyof T) => void;
};
function onChangeGenericFunction<T>(handler: Handler<T & {preset: number}>) {
handler.onChange('preset')
}
// Repro from #13285
function updateIds<T extends Record<K, string>, K extends string>(
obj: T,
idFields: K[],
idMapping: Partial<Record<T[K], T[K]>>
): Record<K, string> {
for (const idField of idFields) {
const newId: T[K] | undefined = idMapping[obj[idField]];
if (newId) {
obj[idField] = newId;
}
}
return obj;
}
// Repro from #13285
function updateIds2<T extends { [x: string]: string }, K extends keyof T>(
obj: T,
key: K,
stringMap: { [oldId: string]: string }
) {
var x = obj[key];
stringMap[x]; // Should be OK.
}
// Repro from #13514
declare function head<T extends Array<any>>(list: T): T[0];
// Repro from #13604
class A<T> {
props: T & { foo: string };
}
class B extends A<{ x: number}> {
f(p: this["props"]) {
p.x;
}
}
// Repro from #13749
class Form<T> {
private childFormFactories: {[K in keyof T]: (v: T[K]) => Form<T[K]>}
public set<K extends keyof T>(prop: K, value: T[K]) {
this.childFormFactories[prop](value)
}
}
// Repro from #13787
class SampleClass<P> {
public props: Readonly<P>;
constructor(props: P) {
this.props = Object.freeze(props);
}
}
interface Foo {
foo: string;
}
declare function merge<T, U>(obj1: T, obj2: U): T & U;
class AnotherSampleClass<T> extends SampleClass<T & Foo> {
constructor(props: T) {
const foo: Foo = { foo: "bar" };
super(merge(props, foo));
}
public brokenMethod() {
this.props.foo.concat;
}
}
new AnotherSampleClass({});
// Positive repro from #17166
function f3<T, K extends Extract<keyof T, string>>(t: T, k: K, tk: T[K]): void {
for (let key in t) {
key = k // ok, K ==> keyof T
t[key] = tk; // ok, T[K] ==> T[keyof T]
}
}
// # 21185
type Predicates<TaggedRecord> = {
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]
}
// Repros from #23592
type Example<T extends { [K in keyof T]: { prop: any } }> = { [K in keyof T]: T[K]["prop"] };
type Result = Example<{ a: { prop: string }; b: { prop: number } }>;
type Helper2<T> = { [K in keyof T]: Extract<T[K], { prop: any }> };
type Example2<T> = { [K in keyof Helper2<T>]: Helper2<T>[K]["prop"] };
type Result2 = Example2<{ 1: { prop: string }; 2: { prop: number } }>;
// Repro from #23618
type DBBoolTable<K extends string> = { [k in K]: 0 | 1 }
enum Flag {
FLAG_1 = "flag_1",
FLAG_2 = "flag_2"
}
type SimpleDBRecord<Flag extends string> = { staticField: number } & DBBoolTable<Flag>
function getFlagsFromSimpleRecord<Flag extends string>(record: SimpleDBRecord<Flag>, flags: Flag[]) {
return record[flags[0]];
}
type DynamicDBRecord<Flag extends string> = ({ dynamicField: number } | { dynamicField: string }) & DBBoolTable<Flag>
function getFlagsFromDynamicRecord<Flag extends string>(record: DynamicDBRecord<Flag>, flags: Flag[]) {
return record[flags[0]];
}
// Repro from #21368
interface I {
foo: string;
}
declare function take<T>(p: T): void;
function fn<T extends I, K extends keyof T>(o: T, k: K) {
take<{} | null | undefined>(o[k]);
take<any>(o[k]);
}
// Repro from #23133
class Unbounded<T> {
foo(x: T[keyof T]) {
let y: {} | undefined | null = x;
}
}
// Repro from #23940
interface I7 {
x: any;
}
type Foo7<T extends number> = T;
declare function f7<K extends keyof I7>(type: K): Foo7<I7[K]>;
// Repro from #21770
type Dict<T extends string> = { [key in T]: number };
type DictDict<V extends string, T extends string> = { [key in V]: Dict<T> };
function ff1<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number {
return dd[k1][k2];
}
function ff2<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number {
const d: Dict<T> = dd[k1];
return d[k2];
}
// Repro from #26409
const cf1 = <T extends { [P in K]: string; } & { cool: string; }, K extends keyof T>(t: T, k: K) =>
{
const s: string = t[k];
t.cool;
};
const cf2 = <T extends { [P in K | "cool"]: string; }, K extends keyof T>(t: T, k: K) =>
{
const s: string = t[k];
t.cool;
};
@@ -1,9 +1,10 @@
tests/cases/conformance/types/mapped/mappedTypeAsClauseRelationships.ts(12,9): error TS2322: Type 'T' is not assignable to type 'Modify<T>'.
tests/cases/conformance/types/mapped/mappedTypeAsClauseRelationships.ts(22,9): error TS2322: Type 'T' is not assignable to type 'ModifyInclOpt<T>'.
tests/cases/conformance/types/mapped/mappedTypeAsClauseRelationships.ts(23,9): error TS2322: Type 'T' is not assignable to type 'FilterExclOpt<T>'.
tests/cases/conformance/types/mapped/mappedTypeAsClauseRelationships.ts(24,9): error TS2322: Type 'T' is not assignable to type 'ModifyExclOpt<T>'.
==== tests/cases/conformance/types/mapped/mappedTypeAsClauseRelationships.ts (3 errors) ====
==== tests/cases/conformance/types/mapped/mappedTypeAsClauseRelationships.ts (4 errors) ====
// From original issue #45212:
type Methods<T> = { [P in keyof T as T[P] extends Function ? P : never]: T[P] };
type H<T> = T[keyof Methods<T>]; // Ok
@@ -28,6 +29,8 @@ tests/cases/conformance/types/mapped/mappedTypeAsClauseRelationships.ts(24,9): e
function fun2<T>(val: T) {
let x: FilterInclOpt<T> = val; // Ok
let y: ModifyInclOpt<T> = val; // Ok
~
!!! error TS2322: Type 'T' is not assignable to type 'ModifyInclOpt<T>'.
let z: FilterExclOpt<T> = val; // Error
~
!!! error TS2322: Type 'T' is not assignable to type 'FilterExclOpt<T>'.
@@ -0,0 +1,105 @@
//// [mappedTypeGenericIndexedAccess.ts]
// Repro from #49242
type Types = {
first: { a1: true };
second: { a2: true };
third: { a3: true };
}
class Test {
entries: { [T in keyof Types]?: Types[T][] };
constructor() {
this.entries = {};
}
addEntry<T extends keyof Types>(name: T, entry: Types[T]) {
if (!this.entries[name]) {
this.entries[name] = [];
}
this.entries[name]?.push(entry);
}
}
// Repro from #49338
type TypesMap = {
[0]: { foo: 'bar'; };
[1]: { a: 'b'; };
};
type P<T extends keyof TypesMap> = { t: T; } & TypesMap[T];
type TypeHandlers = {
[T in keyof TypesMap]?: (p: P<T>) => void;
};
const typeHandlers: TypeHandlers = {
[0]: (p) => console.log(p.foo),
[1]: (p) => console.log(p.a),
};
const onSomeEvent = <T extends keyof TypesMap>(p: P<T>) =>
typeHandlers[p.t]?.(p);
//// [mappedTypeGenericIndexedAccess.js]
"use strict";
// Repro from #49242
var _a;
var Test = /** @class */ (function () {
function Test() {
this.entries = {};
}
Test.prototype.addEntry = function (name, entry) {
var _a;
if (!this.entries[name]) {
this.entries[name] = [];
}
(_a = this.entries[name]) === null || _a === void 0 ? void 0 : _a.push(entry);
};
return Test;
}());
var typeHandlers = (_a = {},
_a[0] = function (p) { return console.log(p.foo); },
_a[1] = function (p) { return console.log(p.a); },
_a);
var onSomeEvent = function (p) { var _a; return (_a = typeHandlers[p.t]) === null || _a === void 0 ? void 0 : _a.call(typeHandlers, p); };
//// [mappedTypeGenericIndexedAccess.d.ts]
declare type Types = {
first: {
a1: true;
};
second: {
a2: true;
};
third: {
a3: true;
};
};
declare class Test {
entries: {
[T in keyof Types]?: Types[T][];
};
constructor();
addEntry<T extends keyof Types>(name: T, entry: Types[T]): void;
}
declare type TypesMap = {
[0]: {
foo: 'bar';
};
[1]: {
a: 'b';
};
};
declare type P<T extends keyof TypesMap> = {
t: T;
} & TypesMap[T];
declare type TypeHandlers = {
[T in keyof TypesMap]?: (p: P<T>) => void;
};
declare const typeHandlers: TypeHandlers;
declare const onSomeEvent: <T extends keyof TypesMap>(p: P<T>) => void | undefined;
@@ -0,0 +1,150 @@
=== tests/cases/compiler/mappedTypeGenericIndexedAccess.ts ===
// Repro from #49242
type Types = {
>Types : Symbol(Types, Decl(mappedTypeGenericIndexedAccess.ts, 0, 0))
first: { a1: true };
>first : Symbol(first, Decl(mappedTypeGenericIndexedAccess.ts, 2, 14))
>a1 : Symbol(a1, Decl(mappedTypeGenericIndexedAccess.ts, 3, 12))
second: { a2: true };
>second : Symbol(second, Decl(mappedTypeGenericIndexedAccess.ts, 3, 24))
>a2 : Symbol(a2, Decl(mappedTypeGenericIndexedAccess.ts, 4, 13))
third: { a3: true };
>third : Symbol(third, Decl(mappedTypeGenericIndexedAccess.ts, 4, 25))
>a3 : Symbol(a3, Decl(mappedTypeGenericIndexedAccess.ts, 5, 12))
}
class Test {
>Test : Symbol(Test, Decl(mappedTypeGenericIndexedAccess.ts, 6, 1))
entries: { [T in keyof Types]?: Types[T][] };
>entries : Symbol(Test.entries, Decl(mappedTypeGenericIndexedAccess.ts, 8, 12))
>T : Symbol(T, Decl(mappedTypeGenericIndexedAccess.ts, 9, 16))
>Types : Symbol(Types, Decl(mappedTypeGenericIndexedAccess.ts, 0, 0))
>Types : Symbol(Types, Decl(mappedTypeGenericIndexedAccess.ts, 0, 0))
>T : Symbol(T, Decl(mappedTypeGenericIndexedAccess.ts, 9, 16))
constructor() {
this.entries = {};
>this.entries : Symbol(Test.entries, Decl(mappedTypeGenericIndexedAccess.ts, 8, 12))
>this : Symbol(Test, Decl(mappedTypeGenericIndexedAccess.ts, 6, 1))
>entries : Symbol(Test.entries, Decl(mappedTypeGenericIndexedAccess.ts, 8, 12))
}
addEntry<T extends keyof Types>(name: T, entry: Types[T]) {
>addEntry : Symbol(Test.addEntry, Decl(mappedTypeGenericIndexedAccess.ts, 13, 5))
>T : Symbol(T, Decl(mappedTypeGenericIndexedAccess.ts, 15, 13))
>Types : Symbol(Types, Decl(mappedTypeGenericIndexedAccess.ts, 0, 0))
>name : Symbol(name, Decl(mappedTypeGenericIndexedAccess.ts, 15, 36))
>T : Symbol(T, Decl(mappedTypeGenericIndexedAccess.ts, 15, 13))
>entry : Symbol(entry, Decl(mappedTypeGenericIndexedAccess.ts, 15, 44))
>Types : Symbol(Types, Decl(mappedTypeGenericIndexedAccess.ts, 0, 0))
>T : Symbol(T, Decl(mappedTypeGenericIndexedAccess.ts, 15, 13))
if (!this.entries[name]) {
>this.entries : Symbol(Test.entries, Decl(mappedTypeGenericIndexedAccess.ts, 8, 12))
>this : Symbol(Test, Decl(mappedTypeGenericIndexedAccess.ts, 6, 1))
>entries : Symbol(Test.entries, Decl(mappedTypeGenericIndexedAccess.ts, 8, 12))
>name : Symbol(name, Decl(mappedTypeGenericIndexedAccess.ts, 15, 36))
this.entries[name] = [];
>this.entries : Symbol(Test.entries, Decl(mappedTypeGenericIndexedAccess.ts, 8, 12))
>this : Symbol(Test, Decl(mappedTypeGenericIndexedAccess.ts, 6, 1))
>entries : Symbol(Test.entries, Decl(mappedTypeGenericIndexedAccess.ts, 8, 12))
>name : Symbol(name, Decl(mappedTypeGenericIndexedAccess.ts, 15, 36))
}
this.entries[name]?.push(entry);
>this.entries[name]?.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>this.entries : Symbol(Test.entries, Decl(mappedTypeGenericIndexedAccess.ts, 8, 12))
>this : Symbol(Test, Decl(mappedTypeGenericIndexedAccess.ts, 6, 1))
>entries : Symbol(Test.entries, Decl(mappedTypeGenericIndexedAccess.ts, 8, 12))
>name : Symbol(name, Decl(mappedTypeGenericIndexedAccess.ts, 15, 36))
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>entry : Symbol(entry, Decl(mappedTypeGenericIndexedAccess.ts, 15, 44))
}
}
// Repro from #49338
type TypesMap = {
>TypesMap : Symbol(TypesMap, Decl(mappedTypeGenericIndexedAccess.ts, 21, 1))
[0]: { foo: 'bar'; };
>[0] : Symbol([0], Decl(mappedTypeGenericIndexedAccess.ts, 25, 17))
>0 : Symbol([0], Decl(mappedTypeGenericIndexedAccess.ts, 25, 17))
>foo : Symbol(foo, Decl(mappedTypeGenericIndexedAccess.ts, 26, 10))
[1]: { a: 'b'; };
>[1] : Symbol([1], Decl(mappedTypeGenericIndexedAccess.ts, 26, 25))
>1 : Symbol([1], Decl(mappedTypeGenericIndexedAccess.ts, 26, 25))
>a : Symbol(a, Decl(mappedTypeGenericIndexedAccess.ts, 27, 10))
};
type P<T extends keyof TypesMap> = { t: T; } & TypesMap[T];
>P : Symbol(P, Decl(mappedTypeGenericIndexedAccess.ts, 28, 2))
>T : Symbol(T, Decl(mappedTypeGenericIndexedAccess.ts, 30, 7))
>TypesMap : Symbol(TypesMap, Decl(mappedTypeGenericIndexedAccess.ts, 21, 1))
>t : Symbol(t, Decl(mappedTypeGenericIndexedAccess.ts, 30, 36))
>T : Symbol(T, Decl(mappedTypeGenericIndexedAccess.ts, 30, 7))
>TypesMap : Symbol(TypesMap, Decl(mappedTypeGenericIndexedAccess.ts, 21, 1))
>T : Symbol(T, Decl(mappedTypeGenericIndexedAccess.ts, 30, 7))
type TypeHandlers = {
>TypeHandlers : Symbol(TypeHandlers, Decl(mappedTypeGenericIndexedAccess.ts, 30, 59))
[T in keyof TypesMap]?: (p: P<T>) => void;
>T : Symbol(T, Decl(mappedTypeGenericIndexedAccess.ts, 33, 5))
>TypesMap : Symbol(TypesMap, Decl(mappedTypeGenericIndexedAccess.ts, 21, 1))
>p : Symbol(p, Decl(mappedTypeGenericIndexedAccess.ts, 33, 29))
>P : Symbol(P, Decl(mappedTypeGenericIndexedAccess.ts, 28, 2))
>T : Symbol(T, Decl(mappedTypeGenericIndexedAccess.ts, 33, 5))
};
const typeHandlers: TypeHandlers = {
>typeHandlers : Symbol(typeHandlers, Decl(mappedTypeGenericIndexedAccess.ts, 36, 5))
>TypeHandlers : Symbol(TypeHandlers, Decl(mappedTypeGenericIndexedAccess.ts, 30, 59))
[0]: (p) => console.log(p.foo),
>[0] : Symbol([0], Decl(mappedTypeGenericIndexedAccess.ts, 36, 36))
>0 : Symbol([0], Decl(mappedTypeGenericIndexedAccess.ts, 36, 36))
>p : Symbol(p, Decl(mappedTypeGenericIndexedAccess.ts, 37, 10))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>p.foo : Symbol(foo, Decl(mappedTypeGenericIndexedAccess.ts, 26, 10))
>p : Symbol(p, Decl(mappedTypeGenericIndexedAccess.ts, 37, 10))
>foo : Symbol(foo, Decl(mappedTypeGenericIndexedAccess.ts, 26, 10))
[1]: (p) => console.log(p.a),
>[1] : Symbol([1], Decl(mappedTypeGenericIndexedAccess.ts, 37, 35))
>1 : Symbol([1], Decl(mappedTypeGenericIndexedAccess.ts, 37, 35))
>p : Symbol(p, Decl(mappedTypeGenericIndexedAccess.ts, 38, 10))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>p.a : Symbol(a, Decl(mappedTypeGenericIndexedAccess.ts, 27, 10))
>p : Symbol(p, Decl(mappedTypeGenericIndexedAccess.ts, 38, 10))
>a : Symbol(a, Decl(mappedTypeGenericIndexedAccess.ts, 27, 10))
};
const onSomeEvent = <T extends keyof TypesMap>(p: P<T>) =>
>onSomeEvent : Symbol(onSomeEvent, Decl(mappedTypeGenericIndexedAccess.ts, 41, 5))
>T : Symbol(T, Decl(mappedTypeGenericIndexedAccess.ts, 41, 21))
>TypesMap : Symbol(TypesMap, Decl(mappedTypeGenericIndexedAccess.ts, 21, 1))
>p : Symbol(p, Decl(mappedTypeGenericIndexedAccess.ts, 41, 47))
>P : Symbol(P, Decl(mappedTypeGenericIndexedAccess.ts, 28, 2))
>T : Symbol(T, Decl(mappedTypeGenericIndexedAccess.ts, 41, 21))
typeHandlers[p.t]?.(p);
>typeHandlers : Symbol(typeHandlers, Decl(mappedTypeGenericIndexedAccess.ts, 36, 5))
>p.t : Symbol(t, Decl(mappedTypeGenericIndexedAccess.ts, 30, 36))
>p : Symbol(p, Decl(mappedTypeGenericIndexedAccess.ts, 41, 47))
>t : Symbol(t, Decl(mappedTypeGenericIndexedAccess.ts, 30, 36))
>p : Symbol(p, Decl(mappedTypeGenericIndexedAccess.ts, 41, 47))
@@ -0,0 +1,147 @@
=== tests/cases/compiler/mappedTypeGenericIndexedAccess.ts ===
// Repro from #49242
type Types = {
>Types : { first: { a1: true;}; second: { a2: true;}; third: { a3: true;}; }
first: { a1: true };
>first : { a1: true; }
>a1 : true
>true : true
second: { a2: true };
>second : { a2: true; }
>a2 : true
>true : true
third: { a3: true };
>third : { a3: true; }
>a3 : true
>true : true
}
class Test {
>Test : Test
entries: { [T in keyof Types]?: Types[T][] };
>entries : { first?: { a1: true; }[] | undefined; second?: { a2: true; }[] | undefined; third?: { a3: true; }[] | undefined; }
constructor() {
this.entries = {};
>this.entries = {} : {}
>this.entries : { first?: { a1: true; }[] | undefined; second?: { a2: true; }[] | undefined; third?: { a3: true; }[] | undefined; }
>this : this
>entries : { first?: { a1: true; }[] | undefined; second?: { a2: true; }[] | undefined; third?: { a3: true; }[] | undefined; }
>{} : {}
}
addEntry<T extends keyof Types>(name: T, entry: Types[T]) {
>addEntry : <T extends keyof Types>(name: T, entry: Types[T]) => void
>name : T
>entry : Types[T]
if (!this.entries[name]) {
>!this.entries[name] : boolean
>this.entries[name] : { first?: { a1: true; }[] | undefined; second?: { a2: true; }[] | undefined; third?: { a3: true; }[] | undefined; }[T]
>this.entries : { first?: { a1: true; }[] | undefined; second?: { a2: true; }[] | undefined; third?: { a3: true; }[] | undefined; }
>this : this
>entries : { first?: { a1: true; }[] | undefined; second?: { a2: true; }[] | undefined; third?: { a3: true; }[] | undefined; }
>name : T
this.entries[name] = [];
>this.entries[name] = [] : never[]
>this.entries[name] : { first?: { a1: true; }[] | undefined; second?: { a2: true; }[] | undefined; third?: { a3: true; }[] | undefined; }[T]
>this.entries : { first?: { a1: true; }[] | undefined; second?: { a2: true; }[] | undefined; third?: { a3: true; }[] | undefined; }
>this : this
>entries : { first?: { a1: true; }[] | undefined; second?: { a2: true; }[] | undefined; third?: { a3: true; }[] | undefined; }
>name : T
>[] : never[]
}
this.entries[name]?.push(entry);
>this.entries[name]?.push(entry) : number | undefined
>this.entries[name]?.push : ((...items: Types[T][]) => number) | undefined
>this.entries[name] : Types[T][] | undefined
>this.entries : { first?: { a1: true; }[] | undefined; second?: { a2: true; }[] | undefined; third?: { a3: true; }[] | undefined; }
>this : this
>entries : { first?: { a1: true; }[] | undefined; second?: { a2: true; }[] | undefined; third?: { a3: true; }[] | undefined; }
>name : T
>push : ((...items: Types[T][]) => number) | undefined
>entry : Types[T]
}
}
// Repro from #49338
type TypesMap = {
>TypesMap : { 0: { foo: 'bar';}; 1: { a: 'b';}; }
[0]: { foo: 'bar'; };
>[0] : { foo: 'bar'; }
>0 : 0
>foo : "bar"
[1]: { a: 'b'; };
>[1] : { a: 'b'; }
>1 : 1
>a : "b"
};
type P<T extends keyof TypesMap> = { t: T; } & TypesMap[T];
>P : P<T>
>t : T
type TypeHandlers = {
>TypeHandlers : { 0?: ((p: P<0>) => void) | undefined; 1?: ((p: P<1>) => void) | undefined; }
[T in keyof TypesMap]?: (p: P<T>) => void;
>p : P<T>
};
const typeHandlers: TypeHandlers = {
>typeHandlers : TypeHandlers
>{ [0]: (p) => console.log(p.foo), [1]: (p) => console.log(p.a),} : { 0: (p: P<0>) => void; 1: (p: P<1>) => void; }
[0]: (p) => console.log(p.foo),
>[0] : (p: P<0>) => void
>0 : 0
>(p) => console.log(p.foo) : (p: P<0>) => void
>p : P<0>
>console.log(p.foo) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>p.foo : "bar"
>p : P<0>
>foo : "bar"
[1]: (p) => console.log(p.a),
>[1] : (p: P<1>) => void
>1 : 1
>(p) => console.log(p.a) : (p: P<1>) => void
>p : P<1>
>console.log(p.a) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>p.a : "b"
>p : P<1>
>a : "b"
};
const onSomeEvent = <T extends keyof TypesMap>(p: P<T>) =>
>onSomeEvent : <T extends keyof TypesMap>(p: P<T>) => void | undefined
><T extends keyof TypesMap>(p: P<T>) => typeHandlers[p.t]?.(p) : <T extends keyof TypesMap>(p: P<T>) => void | undefined
>p : P<T>
typeHandlers[p.t]?.(p);
>typeHandlers[p.t]?.(p) : void | undefined
>typeHandlers[p.t] : ((p: P<T>) => void) | undefined
>typeHandlers : TypeHandlers
>p.t : T
>p : { t: T; } & ({ foo: "bar"; } | { a: "b"; })
>t : T
>p : P<T>
+6 -6
View File
@@ -27,17 +27,17 @@ function boxify<T>(obj: T): Boxified<T> {
for (let k in obj) {
>k : Extract<keyof T, string>
>obj : T
>obj : (T & null) | (T & object)
result[k] = { value: obj[k] };
>result[k] = { value: obj[k] } : { value: T[Extract<keyof T, string>]; }
>result[k] = { value: obj[k] } : { value: (T & object)[Extract<keyof T, string>]; }
>result[k] : Boxified<T>[Extract<keyof T, string>]
>result : Boxified<T>
>k : Extract<keyof T, string>
>{ value: obj[k] } : { value: T[Extract<keyof T, string>]; }
>value : T[Extract<keyof T, string>]
>obj[k] : T[Extract<keyof T, string>]
>obj : T
>{ value: obj[k] } : { value: (T & object)[Extract<keyof T, string>]; }
>value : (T & object)[Extract<keyof T, string>]
>obj[k] : (T & object)[Extract<keyof T, string>]
>obj : T & object
>k : Extract<keyof T, string>
}
return result;
@@ -7,6 +7,20 @@ tests/cases/conformance/types/mapped/mappedTypes6.ts(37,5): error TS2322: Type '
Type 'T[keyof T]' is not assignable to type 'NonNullable<T[P]>'.
Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'NonNullable<T[P]>'.
Type 'T[string]' is not assignable to type 'NonNullable<T[P]>'.
Type 'T[string]' is not assignable to type 'T[P]'.
Type 'string' is not assignable to type 'P'.
'string' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'string | number | symbol'.
Type 'T[keyof T]' is not assignable to type 'T[P]'.
Type 'keyof T' is not assignable to type 'P'.
'keyof T' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'string | number | symbol'.
Type 'string | number | symbol' is not assignable to type 'P'.
'string | number | symbol' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'string | number | symbol'.
Type 'string' is not assignable to type 'P'.
'string' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'string | number | symbol'.
Type 'T[P]' is not assignable to type '{}'.
Type 'T[keyof T]' is not assignable to type '{}'.
Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{}'.
Type 'T[string]' is not assignable to type '{}'.
tests/cases/conformance/types/mapped/mappedTypes6.ts(38,5): error TS2322: Type 'T' is not assignable to type 'Denullified<T>'.
tests/cases/conformance/types/mapped/mappedTypes6.ts(39,5): error TS2322: Type 'Partial<T>' is not assignable to type 'Denullified<T>'.
tests/cases/conformance/types/mapped/mappedTypes6.ts(42,5): error TS2322: Type 'T' is not assignable to type 'Required<T>'.
@@ -77,6 +91,20 @@ tests/cases/conformance/types/mapped/mappedTypes6.ts(120,4): error TS2540: Canno
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'NonNullable<T[P]>'.
!!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'NonNullable<T[P]>'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'NonNullable<T[P]>'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'T[P]'.
!!! error TS2322: Type 'string' is not assignable to type 'P'.
!!! error TS2322: 'string' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'string | number | symbol'.
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'T[P]'.
!!! error TS2322: Type 'keyof T' is not assignable to type 'P'.
!!! error TS2322: 'keyof T' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'string | number | symbol'.
!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'P'.
!!! error TS2322: 'string | number | symbol' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'string | number | symbol'.
!!! error TS2322: Type 'string' is not assignable to type 'P'.
!!! error TS2322: 'string' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'string | number | symbol'.
!!! error TS2322: Type 'T[P]' is not assignable to type '{}'.
!!! error TS2322: Type 'T[keyof T]' is not assignable to type '{}'.
!!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{}'.
!!! error TS2322: Type 'T[string]' is not assignable to type '{}'.
w = y; // Error
~
!!! error TS2322: Type 'T' is not assignable to type 'Denullified<T>'.
@@ -0,0 +1,54 @@
tests/cases/conformance/types/mapped/mappedTypesAndObjects.ts(25,11): error TS2430: Interface 'E1<T>' incorrectly extends interface 'Base'.
Types of property 'foo' are incompatible.
Type 'T' is not assignable to type '{ [key: string]: any; }'.
==== tests/cases/conformance/types/mapped/mappedTypesAndObjects.ts (1 errors) ====
function f1<T>(x: Partial<T>, y: Readonly<T>) {
let obj: {};
obj = x;
obj = y;
}
function f2<T>(x: Partial<T>, y: Readonly<T>) {
let obj: { [x: string]: any };
obj = x;
obj = y;
}
function f3<T>(x: Partial<T>) {
x = {};
}
// Repro from #12900
interface Base {
foo: { [key: string]: any };
bar: any;
baz: any;
}
interface E1<T> extends Base {
~~
!!! error TS2430: Interface 'E1<T>' incorrectly extends interface 'Base'.
!!! error TS2430: Types of property 'foo' are incompatible.
!!! error TS2430: Type 'T' is not assignable to type '{ [key: string]: any; }'.
!!! related TS2208 tests/cases/conformance/types/mapped/mappedTypesAndObjects.ts:25:14: This type parameter probably needs an `extends object` constraint.
foo: T;
}
interface Something { name: string, value: string };
interface E2 extends Base {
foo: Partial<Something>; // or other mapped type
}
interface E3<T> extends Base {
foo: Partial<T>; // or other mapped type
}
// Repro from #13747
class Form<T> {
private values: {[P in keyof T]?: T[P]} = {}
}
@@ -144,7 +144,7 @@ if (xUnknown == null) {
} else {
xUnknown
>xUnknown : unknown
>xUnknown : {}
}
if (xUnknown != null) {
@@ -153,7 +153,7 @@ if (xUnknown != null) {
>null : null
xUnknown;
>xUnknown : unknown
>xUnknown : {}
} else {
xUnknown;
@@ -552,14 +552,14 @@ function multipleGenericFuse<X extends L | number, Y extends R | number>(xy: X |
case 'function': return [xy, 1];
>'function' : "function"
>[xy, 1] : [X, 1]
>xy : X
>[xy, 1] : [X & Function, 1]
>xy : X & Function
>1 : 1
case 'object': return [xy, 'two'];
>'object' : "object"
>[xy, 'two'] : [Y, string]
>xy : Y
>[xy, 'two'] : [Y & object, string]
>xy : Y & object
>'two' : "two"
case 'number': return [xy]
@@ -843,7 +843,7 @@ function narrowingNarrows(x: {} | undefined) {
case 'object': const _: {} = x; return;
>'object' : "object"
>_ : {}
>x : {}
>x : object
case 'string': assertString(x); return;
>'string' : "string"
@@ -1092,14 +1092,14 @@ function multipleGenericFuseWithBoth<X extends L | number, Y extends R | number>
case `function`: return [xy, 1];
>`function` : "function"
>[xy, 1] : [X, 1]
>xy : X
>[xy, 1] : [X & Function, 1]
>xy : X & Function
>1 : 1
case 'object': return [xy, 'two'];
>'object' : "object"
>[xy, 'two'] : [Y, string]
>xy : Y
>[xy, 'two'] : [Y & object, string]
>xy : Y & object
>'two' : "two"
case `number`: return [xy]
@@ -35,7 +35,7 @@ function foo(x: unknown, b: boolean) {
>x : unknown
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {}
>'object' : "object"
x.toString();
@@ -51,7 +51,7 @@ function foo(x: unknown, b: boolean) {
>x : unknown
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {}
>'object' : "object"
x.toString();
@@ -67,7 +67,7 @@ function foo(x: unknown, b: boolean) {
>b : boolean
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {}
>'object' : "object"
x.toString();
@@ -85,7 +85,7 @@ function foo(x: unknown, b: boolean) {
>b : true
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {}
>'object' : "object"
x.toString();
@@ -107,7 +107,7 @@ function foo(x: unknown, b: boolean) {
>b : true
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {}
>'object' : "object"
x.toString();
@@ -130,7 +130,7 @@ function f1(x: unknown): any {
>x : unknown
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>x : {}
>'object' : "object"
>x.hasOwnProperty('x') : boolean
>x.hasOwnProperty : (v: PropertyKey) => boolean
@@ -35,7 +35,7 @@ function f2<T>(x: (T & F) | T & string) {
>"function" : "function"
x;
>x : (T & F) | (T & string)
>x : T & F
}
else {
x;
+1 -1
View File
@@ -180,7 +180,7 @@ declare function infiniteLoop1(): void;
declare function infiniteLoop2(): never;
declare function move1(direction: "up" | "down"): 1 | -1;
declare function move2(direction: "up" | "down"): 1 | -1;
declare function check<T>(x: T | undefined): T;
declare function check<T>(x: T | undefined): NonNullable<T>;
declare class C {
void1(): void;
void2(): void;
+2 -2
View File
@@ -112,11 +112,11 @@ function move2(direction: "up" | "down") {
}
function check<T>(x: T | undefined) {
>check : <T>(x: T | undefined) => T
>check : <T>(x: T | undefined) => NonNullable<T>
>x : T | undefined
return x || error("Undefined value");
>x || error("Undefined value") : T
>x || error("Undefined value") : NonNullable<T>
>x : T | undefined
>error("Undefined value") : never
>error : (message: string) => never
@@ -0,0 +1,44 @@
/index.cts(4,21): error TS2307: Cannot find module 'dedent4' or its corresponding type declarations.
/index.mts(4,21): error TS2307: Cannot find module 'dedent4' or its corresponding type declarations.
==== /node_modules/@types/dedent/package.json (0 errors) ====
{ "name": "@types/dedent", "version": "1.0.0", "main": "" }
==== /node_modules/@types/dedent2/package.json (0 errors) ====
{ "name": "@types/dedent2", "version": "1.0.0", "main": "asdfasdfasdf" }
==== /node_modules/@types/dedent3/package.json (0 errors) ====
{ "name": "@types/dedent3", "version": "1.0.0", "main": "asdfasdfasdf", "exports": null }
==== /node_modules/@types/dedent4/package.json (0 errors) ====
{ "name": "@types/dedent4", "version": "1.0.0", "main": "asdfasdfasdf", "exports": "./asdfasdfasdf" }
==== /node_modules/@types/dedent/index.d.ts (0 errors) ====
export {};
==== /node_modules/@types/dedent2/index.d.ts (0 errors) ====
export {};
==== /node_modules/@types/dedent3/index.d.ts (0 errors) ====
export {};
==== /node_modules/@types/dedent4/index.d.ts (0 errors) ====
export {};
==== /index.mts (1 errors) ====
import dedent from "dedent";
import dedent2 from "dedent2";
import dedent3 from "dedent3";
import dedent4 from "dedent4"; // Error
~~~~~~~~~
!!! error TS2307: Cannot find module 'dedent4' or its corresponding type declarations.
==== /index.cts (1 errors) ====
import dedent from "dedent";
import dedent2 from "dedent2";
import dedent3 from "dedent3";
import dedent4 from "dedent4"; // Error
~~~~~~~~~
!!! error TS2307: Cannot find module 'dedent4' or its corresponding type declarations.
@@ -0,0 +1,44 @@
//// [tests/cases/compiler/nodeNextImportModeImplicitIndexResolution2.ts] ////
//// [package.json]
{ "name": "@types/dedent", "version": "1.0.0", "main": "" }
//// [package.json]
{ "name": "@types/dedent2", "version": "1.0.0", "main": "asdfasdfasdf" }
//// [package.json]
{ "name": "@types/dedent3", "version": "1.0.0", "main": "asdfasdfasdf", "exports": null }
//// [package.json]
{ "name": "@types/dedent4", "version": "1.0.0", "main": "asdfasdfasdf", "exports": "./asdfasdfasdf" }
//// [index.d.ts]
export {};
//// [index.d.ts]
export {};
//// [index.d.ts]
export {};
//// [index.d.ts]
export {};
//// [index.mts]
import dedent from "dedent";
import dedent2 from "dedent2";
import dedent3 from "dedent3";
import dedent4 from "dedent4"; // Error
//// [index.cts]
import dedent from "dedent";
import dedent2 from "dedent2";
import dedent3 from "dedent3";
import dedent4 from "dedent4"; // Error
//// [index.mjs]
export {};
//// [index.cjs]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,38 @@
=== /node_modules/@types/dedent/index.d.ts ===
export {};
No type information for this code.
No type information for this code.=== /node_modules/@types/dedent2/index.d.ts ===
export {};
No type information for this code.
No type information for this code.=== /node_modules/@types/dedent3/index.d.ts ===
export {};
No type information for this code.
No type information for this code.=== /node_modules/@types/dedent4/index.d.ts ===
export {};
No type information for this code.
No type information for this code.=== /index.mts ===
import dedent from "dedent";
>dedent : Symbol(dedent, Decl(index.mts, 0, 6))
import dedent2 from "dedent2";
>dedent2 : Symbol(dedent2, Decl(index.mts, 1, 6))
import dedent3 from "dedent3";
>dedent3 : Symbol(dedent3, Decl(index.mts, 2, 6))
import dedent4 from "dedent4"; // Error
>dedent4 : Symbol(dedent4, Decl(index.mts, 3, 6))
=== /index.cts ===
import dedent from "dedent";
>dedent : Symbol(dedent, Decl(index.cts, 0, 6))
import dedent2 from "dedent2";
>dedent2 : Symbol(dedent2, Decl(index.cts, 1, 6))
import dedent3 from "dedent3";
>dedent3 : Symbol(dedent3, Decl(index.cts, 2, 6))
import dedent4 from "dedent4"; // Error
>dedent4 : Symbol(dedent4, Decl(index.cts, 3, 6))
@@ -0,0 +1,38 @@
=== /node_modules/@types/dedent/index.d.ts ===
export {};
No type information for this code.
No type information for this code.=== /node_modules/@types/dedent2/index.d.ts ===
export {};
No type information for this code.
No type information for this code.=== /node_modules/@types/dedent3/index.d.ts ===
export {};
No type information for this code.
No type information for this code.=== /node_modules/@types/dedent4/index.d.ts ===
export {};
No type information for this code.
No type information for this code.=== /index.mts ===
import dedent from "dedent";
>dedent : typeof dedent
import dedent2 from "dedent2";
>dedent2 : typeof dedent2
import dedent3 from "dedent3";
>dedent3 : typeof dedent3
import dedent4 from "dedent4"; // Error
>dedent4 : any
=== /index.cts ===
import dedent from "dedent";
>dedent : typeof dedent
import dedent2 from "dedent2";
>dedent2 : typeof dedent2
import dedent3 from "dedent3";
>dedent3 : typeof dedent3
import dedent4 from "dedent4"; // Error
>dedent4 : any
@@ -25,7 +25,7 @@ function fn<T extends string | undefined, U extends string>(one: T, two: U) {
foo(two!);
>foo(two!) : void
>foo : (p: string) => void
>two! : NonNullable<U>
>two! : U
>two : U
foo(three!); // this line is the important one
@@ -0,0 +1,85 @@
//// [nonNullableTypes1.ts]
function f1<T>(x: T) {
let y = x || "hello"; // NonNullable<T> | string
}
function error(): never {
throw new Error();
}
function f2<T>(x: T) { // NonNullable<T>
return x || error();
}
function f3(x: unknown) {
let y = x!; // {}
}
function f4<T extends { x: string } | undefined>(obj: T) {
if (obj?.x === "hello") {
obj; // NonNullable<T>
}
if (obj?.x) {
obj; // NonNullable<T>
}
if (typeof obj?.x === "string") {
obj; // NonNullable<T>
}
}
class A {
x = "hello";
foo() {
let zz = this?.x; // string
}
}
//// [nonNullableTypes1.js]
"use strict";
function f1(x) {
var y = x || "hello"; // NonNullable<T> | string
}
function error() {
throw new Error();
}
function f2(x) {
return x || error();
}
function f3(x) {
var y = x; // {}
}
function f4(obj) {
if ((obj === null || obj === void 0 ? void 0 : obj.x) === "hello") {
obj; // NonNullable<T>
}
if (obj === null || obj === void 0 ? void 0 : obj.x) {
obj; // NonNullable<T>
}
if (typeof (obj === null || obj === void 0 ? void 0 : obj.x) === "string") {
obj; // NonNullable<T>
}
}
var A = /** @class */ (function () {
function A() {
this.x = "hello";
}
A.prototype.foo = function () {
var zz = this === null || this === void 0 ? void 0 : this.x; // string
};
return A;
}());
//// [nonNullableTypes1.d.ts]
declare function f1<T>(x: T): void;
declare function error(): never;
declare function f2<T>(x: T): NonNullable<T>;
declare function f3(x: unknown): void;
declare function f4<T extends {
x: string;
} | undefined>(obj: T): void;
declare class A {
x: string;
foo(): void;
}
@@ -0,0 +1,89 @@
=== tests/cases/compiler/nonNullableTypes1.ts ===
function f1<T>(x: T) {
>f1 : Symbol(f1, Decl(nonNullableTypes1.ts, 0, 0))
>T : Symbol(T, Decl(nonNullableTypes1.ts, 0, 12))
>x : Symbol(x, Decl(nonNullableTypes1.ts, 0, 15))
>T : Symbol(T, Decl(nonNullableTypes1.ts, 0, 12))
let y = x || "hello"; // NonNullable<T> | string
>y : Symbol(y, Decl(nonNullableTypes1.ts, 1, 7))
>x : Symbol(x, Decl(nonNullableTypes1.ts, 0, 15))
}
function error(): never {
>error : Symbol(error, Decl(nonNullableTypes1.ts, 2, 1))
throw new Error();
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
}
function f2<T>(x: T) { // NonNullable<T>
>f2 : Symbol(f2, Decl(nonNullableTypes1.ts, 6, 1))
>T : Symbol(T, Decl(nonNullableTypes1.ts, 8, 12))
>x : Symbol(x, Decl(nonNullableTypes1.ts, 8, 15))
>T : Symbol(T, Decl(nonNullableTypes1.ts, 8, 12))
return x || error();
>x : Symbol(x, Decl(nonNullableTypes1.ts, 8, 15))
>error : Symbol(error, Decl(nonNullableTypes1.ts, 2, 1))
}
function f3(x: unknown) {
>f3 : Symbol(f3, Decl(nonNullableTypes1.ts, 10, 1))
>x : Symbol(x, Decl(nonNullableTypes1.ts, 12, 12))
let y = x!; // {}
>y : Symbol(y, Decl(nonNullableTypes1.ts, 13, 7))
>x : Symbol(x, Decl(nonNullableTypes1.ts, 12, 12))
}
function f4<T extends { x: string } | undefined>(obj: T) {
>f4 : Symbol(f4, Decl(nonNullableTypes1.ts, 14, 1))
>T : Symbol(T, Decl(nonNullableTypes1.ts, 16, 12))
>x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
>T : Symbol(T, Decl(nonNullableTypes1.ts, 16, 12))
if (obj?.x === "hello") {
>obj?.x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
>x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
obj; // NonNullable<T>
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
}
if (obj?.x) {
>obj?.x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
>x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
obj; // NonNullable<T>
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
}
if (typeof obj?.x === "string") {
>obj?.x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
>x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
obj; // NonNullable<T>
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
}
}
class A {
>A : Symbol(A, Decl(nonNullableTypes1.ts, 26, 1))
x = "hello";
>x : Symbol(A.x, Decl(nonNullableTypes1.ts, 28, 9))
foo() {
>foo : Symbol(A.foo, Decl(nonNullableTypes1.ts, 29, 16))
let zz = this?.x; // string
>zz : Symbol(zz, Decl(nonNullableTypes1.ts, 31, 11))
>this?.x : Symbol(A.x, Decl(nonNullableTypes1.ts, 28, 9))
>this : Symbol(A, Decl(nonNullableTypes1.ts, 26, 1))
>x : Symbol(A.x, Decl(nonNullableTypes1.ts, 28, 9))
}
}
@@ -0,0 +1,95 @@
=== tests/cases/compiler/nonNullableTypes1.ts ===
function f1<T>(x: T) {
>f1 : <T>(x: T) => void
>x : T
let y = x || "hello"; // NonNullable<T> | string
>y : string | NonNullable<T>
>x || "hello" : "hello" | NonNullable<T>
>x : T
>"hello" : "hello"
}
function error(): never {
>error : () => never
throw new Error();
>new Error() : Error
>Error : ErrorConstructor
}
function f2<T>(x: T) { // NonNullable<T>
>f2 : <T>(x: T) => NonNullable<T>
>x : T
return x || error();
>x || error() : NonNullable<T>
>x : T
>error() : never
>error : () => never
}
function f3(x: unknown) {
>f3 : (x: unknown) => void
>x : unknown
let y = x!; // {}
>y : {}
>x! : {}
>x : unknown
}
function f4<T extends { x: string } | undefined>(obj: T) {
>f4 : <T extends { x: string; } | undefined>(obj: T) => void
>x : string
>obj : T
if (obj?.x === "hello") {
>obj?.x === "hello" : boolean
>obj?.x : string | undefined
>obj : { x: string; } | undefined
>x : string | undefined
>"hello" : "hello"
obj; // NonNullable<T>
>obj : NonNullable<T>
}
if (obj?.x) {
>obj?.x : string | undefined
>obj : { x: string; } | undefined
>x : string | undefined
obj; // NonNullable<T>
>obj : NonNullable<T>
}
if (typeof obj?.x === "string") {
>typeof obj?.x === "string" : boolean
>typeof obj?.x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>obj?.x : string | undefined
>obj : { x: string; } | undefined
>x : string | undefined
>"string" : "string"
obj; // NonNullable<T>
>obj : NonNullable<T>
}
}
class A {
>A : A
x = "hello";
>x : string
>"hello" : "hello"
foo() {
>foo : () => void
let zz = this?.x; // string
>zz : string
>this?.x : string
>this : this
>x : string
}
}
@@ -1,6 +1,5 @@
tests/cases/conformance/types/nonPrimitive/nonPrimitiveUnionIntersection.ts(1,5): error TS2322: Type 'string' is not assignable to type 'never'.
tests/cases/conformance/types/nonPrimitive/nonPrimitiveUnionIntersection.ts(3,5): error TS2322: Type 'number' is not assignable to type 'object & {}'.
Type 'number' is not assignable to type 'object'.
tests/cases/conformance/types/nonPrimitive/nonPrimitiveUnionIntersection.ts(3,5): error TS2322: Type 'number' is not assignable to type 'object'.
tests/cases/conformance/types/nonPrimitive/nonPrimitiveUnionIntersection.ts(4,1): error TS2322: Type 'string' is not assignable to type 'never'.
tests/cases/conformance/types/nonPrimitive/nonPrimitiveUnionIntersection.ts(8,38): error TS2322: Type '{ bar: string; }' is not assignable to type 'object & { err: string; }'.
Object literal may only specify known properties, and 'bar' does not exist in type 'object & { err: string; }'.
@@ -13,8 +12,7 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveUnionIntersection.ts(8,38
var b: object | string = ""; // ok
var c: object & {} = 123; // error
~
!!! error TS2322: Type 'number' is not assignable to type 'object & {}'.
!!! error TS2322: Type 'number' is not assignable to type 'object'.
!!! error TS2322: Type 'number' is not assignable to type 'object'.
a = b; // error
~
!!! error TS2322: Type 'string' is not assignable to type 'never'.
@@ -8,7 +8,7 @@ var b: object | string = ""; // ok
>"" : ""
var c: object & {} = 123; // error
>c : object & {}
>c : object
>123 : 123
a = b; // error
@@ -22,7 +22,7 @@ b = a; // ok
>a : never
const foo: object & {} = {bar: 'bar'}; // ok
>foo : object & {}
>foo : object
>{bar: 'bar'} : { bar: string; }
>bar : string
>'bar' : "bar"
@@ -75,8 +75,8 @@ const aa6 = a6 ?? 'whatever'
>'whatever' : "whatever"
const aa7 = a7 ?? 'whatever'
>aa7 : unknown
>a7 ?? 'whatever' : unknown
>aa7 : {}
>a7 ?? 'whatever' : {}
>a7 : unknown
>'whatever' : "whatever"
@@ -75,8 +75,8 @@ const aa6 = a6 ?? 'whatever'
>'whatever' : "whatever"
const aa7 = a7 ?? 'whatever'
>aa7 : unknown
>a7 ?? 'whatever' : unknown
>aa7 : {}
>a7 ?? 'whatever' : {}
>a7 : unknown
>'whatever' : "whatever"
@@ -0,0 +1,26 @@
tests/cases/compiler/omittedExpressionForOfLoop.ts(1,19): error TS2304: Cannot find name 'doesNotExist'.
tests/cases/compiler/omittedExpressionForOfLoop.ts(4,19): error TS2532: Object is possibly 'undefined'.
tests/cases/compiler/omittedExpressionForOfLoop.ts(7,12): error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator.
tests/cases/compiler/omittedExpressionForOfLoop.ts(10,12): error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator.
==== tests/cases/compiler/omittedExpressionForOfLoop.ts (4 errors) ====
for (const [,] of doesNotExist) {
~~~~~~~~~~~~
!!! error TS2304: Cannot find name 'doesNotExist'.
}
for (const [,] of undefined) {
~~~~~~~~~
!!! error TS2532: Object is possibly 'undefined'.
}
for (const [,] of []) {
~~~
!!! error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator.
}
for (const [] of []) {
~~
!!! error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator.
}
@@ -0,0 +1,23 @@
//// [omittedExpressionForOfLoop.ts]
for (const [,] of doesNotExist) {
}
for (const [,] of undefined) {
}
for (const [,] of []) {
}
for (const [] of []) {
}
//// [omittedExpressionForOfLoop.js]
"use strict";
for (const [,] of doesNotExist) {
}
for (const [,] of undefined) {
}
for (const [,] of []) {
}
for (const [] of []) {
}
@@ -0,0 +1,13 @@
=== tests/cases/compiler/omittedExpressionForOfLoop.ts ===
for (const [,] of doesNotExist) {
}
for (const [,] of undefined) {
>undefined : Symbol(undefined)
}
for (const [,] of []) {
}
for (const [] of []) {
}
@@ -0,0 +1,19 @@
=== tests/cases/compiler/omittedExpressionForOfLoop.ts ===
for (const [,] of doesNotExist) {
> : undefined
>doesNotExist : any
}
for (const [,] of undefined) {
> : undefined
>undefined : undefined
}
for (const [,] of []) {
> : undefined
>[] : never[]
}
for (const [] of []) {
>[] : never[]
}
@@ -28,10 +28,10 @@ class A {
this?.getA().#b; // Error
>this?.getA().#b : A | undefined
>this?.getA() : A | undefined
>this?.getA : (() => A) | undefined
>this?.getA() : A
>this?.getA : () => A
>this : this
>getA : (() => A) | undefined
>getA : () => A
}
}
@@ -179,7 +179,7 @@ const arrayOfTypes = [PropTypes.string, PropTypes.bool, PropTypes.shape({
// TS checking
const propTypes: PropTypesMap = {
>propTypes : PropTypes.ValidationMap<Props>
>{ any: PropTypes.any, array: PropTypes.array.isRequired, bool: PropTypes.bool.isRequired, shape: PropTypes.shape(innerProps).isRequired, oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired,} : { any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>; oneOfType: PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>; }
>{ any: PropTypes.any, array: PropTypes.array.isRequired, bool: PropTypes.bool.isRequired, shape: PropTypes.shape(innerProps).isRequired, oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired,} : { any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>; oneOfType: PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>; }
any: PropTypes.any,
>any : PropTypes.Requireable<any>
@@ -204,31 +204,31 @@ const propTypes: PropTypesMap = {
>isRequired : PropTypes.Validator<boolean>
shape: PropTypes.shape(innerProps).isRequired,
>shape : PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>
>PropTypes.shape(innerProps).isRequired : PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>
>shape : PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>
>PropTypes.shape(innerProps).isRequired : PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>
>PropTypes.shape(innerProps) : PropTypes.Requireable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>
>PropTypes.shape : <P extends PropTypes.ValidationMap<any>>(type: P) => PropTypes.Requireable<PropTypes.InferProps<P>>
>PropTypes : typeof PropTypes
>shape : <P extends PropTypes.ValidationMap<any>>(type: P) => PropTypes.Requireable<PropTypes.InferProps<P>>
>innerProps : { foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }
>isRequired : PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>
>isRequired : PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>
oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired,
>oneOfType : PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>
>PropTypes.oneOfType(arrayOfTypes).isRequired : PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>
>PropTypes.oneOfType(arrayOfTypes) : PropTypes.Requireable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>
>oneOfType : PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>
>PropTypes.oneOfType(arrayOfTypes).isRequired : PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>
>PropTypes.oneOfType(arrayOfTypes) : PropTypes.Requireable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>
>PropTypes.oneOfType : <T extends PropTypes.Validator<any>>(types: T[]) => PropTypes.Requireable<NonNullable<PropTypes.InferType<T>>>
>PropTypes : typeof PropTypes
>oneOfType : <T extends PropTypes.Validator<any>>(types: T[]) => PropTypes.Requireable<NonNullable<PropTypes.InferType<T>>>
>arrayOfTypes : (PropTypes.Requireable<boolean> | PropTypes.Requireable<string> | PropTypes.Requireable<PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>)[]
>isRequired : PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>
>isRequired : PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>
};
// JS checking
const propTypesWithoutAnnotation = {
>propTypesWithoutAnnotation : { any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>; oneOfType: PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>; }
>{ any: PropTypes.any, array: PropTypes.array.isRequired, bool: PropTypes.bool.isRequired, shape: PropTypes.shape(innerProps).isRequired, oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired,} : { any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>; oneOfType: PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>; }
>propTypesWithoutAnnotation : { any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>; oneOfType: PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>; }
>{ any: PropTypes.any, array: PropTypes.array.isRequired, bool: PropTypes.bool.isRequired, shape: PropTypes.shape(innerProps).isRequired, oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired,} : { any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>; oneOfType: PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>; }
any: PropTypes.any,
>any : PropTypes.Requireable<any>
@@ -253,24 +253,24 @@ const propTypesWithoutAnnotation = {
>isRequired : PropTypes.Validator<boolean>
shape: PropTypes.shape(innerProps).isRequired,
>shape : PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>
>PropTypes.shape(innerProps).isRequired : PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>
>shape : PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>
>PropTypes.shape(innerProps).isRequired : PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>
>PropTypes.shape(innerProps) : PropTypes.Requireable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>
>PropTypes.shape : <P extends PropTypes.ValidationMap<any>>(type: P) => PropTypes.Requireable<PropTypes.InferProps<P>>
>PropTypes : typeof PropTypes
>shape : <P extends PropTypes.ValidationMap<any>>(type: P) => PropTypes.Requireable<PropTypes.InferProps<P>>
>innerProps : { foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }
>isRequired : PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>
>isRequired : PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>
oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired,
>oneOfType : PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>
>PropTypes.oneOfType(arrayOfTypes).isRequired : PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>
>PropTypes.oneOfType(arrayOfTypes) : PropTypes.Requireable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>
>oneOfType : PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>
>PropTypes.oneOfType(arrayOfTypes).isRequired : PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>
>PropTypes.oneOfType(arrayOfTypes) : PropTypes.Requireable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>
>PropTypes.oneOfType : <T extends PropTypes.Validator<any>>(types: T[]) => PropTypes.Requireable<NonNullable<PropTypes.InferType<T>>>
>PropTypes : typeof PropTypes
>oneOfType : <T extends PropTypes.Validator<any>>(types: T[]) => PropTypes.Requireable<NonNullable<PropTypes.InferType<T>>>
>arrayOfTypes : (PropTypes.Requireable<boolean> | PropTypes.Requireable<string> | PropTypes.Requireable<PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>)[]
>isRequired : PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>
>isRequired : PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>
};
@@ -280,9 +280,9 @@ type ExtractedProps = PropTypes.InferProps<typeof propTypes>;
>propTypes : PropTypes.ValidationMap<Props>
type ExtractedPropsWithoutAnnotation = PropTypes.InferProps<typeof propTypesWithoutAnnotation>;
>ExtractedPropsWithoutAnnotation : PropTypes.InferPropsInner<Pick<{ any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>; oneOfType: PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>; }, PropTypes.RequiredKeys<{ any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>; oneOfType: PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>; }>>> & Partial<PropTypes.InferPropsInner<Pick<{ any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>; oneOfType: PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>; }, "any">>>
>ExtractedPropsWithoutAnnotation : PropTypes.InferPropsInner<Pick<{ any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>; oneOfType: PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>; }, PropTypes.RequiredKeys<{ any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>; oneOfType: PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>; }>>> & Partial<PropTypes.InferPropsInner<Pick<{ any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>; oneOfType: PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>; }, "any">>>
>PropTypes : any
>propTypesWithoutAnnotation : { any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>; oneOfType: PropTypes.Validator<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>; }
>propTypesWithoutAnnotation : { any: PropTypes.Requireable<any>; array: PropTypes.Validator<any[]>; bool: PropTypes.Validator<boolean>; shape: PropTypes.Validator<NonNullable<PropTypes.InferProps<{ foo: PropTypes.Validator<string>; bar: PropTypes.Requireable<boolean>; baz: PropTypes.Requireable<any>; }>>>; oneOfType: PropTypes.Validator<NonNullable<NonNullable<string | boolean | PropTypes.InferProps<{ foo: PropTypes.Requireable<string>; bar: PropTypes.Validator<number>; }>>>>; }
type ExtractPropsMatch = ExtractedProps extends ExtractedPropsWithoutAnnotation ? true : false;
>ExtractPropsMatch : true
@@ -1,7 +1,7 @@
tests/cases/compiler/recursiveTupleTypeInference.ts(23,5): error TS2345: Argument of type '{ b: A; }' is not assignable to parameter of type 'G<{ b: unknown; }>'.
Types of property 'b' are incompatible.
Type 'A' is not assignable to type '[[[[[[[[[[[[any, "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"]'.
Type 'string' is not assignable to type '[[[[[[[[[[[[any, "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"]'.
Type 'A' is not assignable to type '[never, "null"]'.
Type 'string' is not assignable to type '[never, "null"]'.
==== tests/cases/compiler/recursiveTupleTypeInference.ts (1 errors) ====
@@ -31,6 +31,6 @@ tests/cases/compiler/recursiveTupleTypeInference.ts(23,5): error TS2345: Argumen
~~
!!! error TS2345: Argument of type '{ b: A; }' is not assignable to parameter of type 'G<{ b: unknown; }>'.
!!! error TS2345: Types of property 'b' are incompatible.
!!! error TS2345: Type 'A' is not assignable to type '[[[[[[[[[[[[any, "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"]'.
!!! error TS2345: Type 'string' is not assignable to type '[[[[[[[[[[[[any, "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"], "null"]'.
!!! error TS2345: Type 'A' is not assignable to type '[never, "null"]'.
!!! error TS2345: Type 'string' is not assignable to type '[never, "null"]'.
@@ -15,7 +15,7 @@ function JustConditional<T>(): ConditionalType<T> {
>JustConditional : <T>() => ConditionalType<T>
return ConditionalOrUndefined<T>()!; // shouldn't error
>ConditionalOrUndefined<T>()! : NonNullable<ConditionalType<T>>
>ConditionalOrUndefined<T>()! : ConditionalType<T>
>ConditionalOrUndefined<T>() : ConditionalType<T> | undefined
>ConditionalOrUndefined : <T>() => ConditionalType<T> | undefined
}
@@ -111,7 +111,7 @@ declare function f5<S, T extends undefined>(a: S | T): S | T;
declare function f6<T extends object | undefined>(a: T): T;
declare function g1<T extends {}, A extends {
z: (T | undefined) & T;
}>(a: A): (T | undefined) & T;
}>(a: A): T | (undefined & T);
interface DatafulFoo<T> {
data: T;
}
@@ -56,19 +56,19 @@ function f6<T extends object | undefined>(a: T) {
// Repro from #46976
function g1<T extends {}, A extends { z: (T | undefined) & T }>(a: A) {
>g1 : <T extends {}, A extends { z: (T | undefined) & T; }>(a: A) => (T | undefined) & T
>z : (T | undefined) & T
>g1 : <T extends {}, A extends { z: (T | undefined) & T; }>(a: A) => T | (undefined & T)
>z : T | (undefined & T)
>a : A
const { z } = a;
>z : (T | undefined) & T
>z : T | (undefined & T)
>a : A
return {
>{ ...z } : (T | undefined) & T
>{ ...z } : T | (undefined & T)
...z
>z : (T | undefined) & T
>z : T | (undefined & T)
};
}
@@ -98,9 +98,9 @@ class Foo<T extends string> {
this.data.toLocaleLowerCase();
>this.data.toLocaleLowerCase() : string
>this.data.toLocaleLowerCase : (locales?: string | string[] | undefined) => string
>this.data : (T | undefined) & T
>this.data : T | (undefined & T)
>this : this & DatafulFoo<T>
>data : (T | undefined) & T
>data : T | (undefined & T)
>toLocaleLowerCase : (locales?: string | string[] | undefined) => string
}
}
@@ -6,7 +6,6 @@ error TS2318: Cannot find global type 'Number'.
error TS2318: Cannot find global type 'Object'.
error TS2318: Cannot find global type 'RegExp'.
error TS2318: Cannot find global type 'String'.
tests/cases/compiler/strictNullNotNullIndexTypeNoLib.ts(10,28): error TS2339: Property 'name' does not exist on type 'T["params"]'.
!!! error TS2318: Cannot find global type 'Array'.
@@ -17,7 +16,7 @@ tests/cases/compiler/strictNullNotNullIndexTypeNoLib.ts(10,28): error TS2339: Pr
!!! error TS2318: Cannot find global type 'Object'.
!!! error TS2318: Cannot find global type 'RegExp'.
!!! error TS2318: Cannot find global type 'String'.
==== tests/cases/compiler/strictNullNotNullIndexTypeNoLib.ts (1 errors) ====
==== tests/cases/compiler/strictNullNotNullIndexTypeNoLib.ts (0 errors) ====
type Readonly<T> = {readonly [K in keyof T]: T[K]}
interface A {
params?: { name: string; };
@@ -28,8 +27,6 @@ tests/cases/compiler/strictNullNotNullIndexTypeNoLib.ts(10,28): error TS2339: Pr
m() {
this.attrs.params!.name;
~~~~
!!! error TS2339: Property 'name' does not exist on type 'T["params"]'.
}
}
@@ -29,11 +29,13 @@ class Test<T extends A> {
>m : Symbol(Test.m, Decl(strictNullNotNullIndexTypeNoLib.ts, 6, 23))
this.attrs.params!.name;
>this.attrs.params!.name : Symbol(name, Decl(strictNullNotNullIndexTypeNoLib.ts, 2, 14))
>this.attrs.params : Symbol(params, Decl(strictNullNotNullIndexTypeNoLib.ts, 1, 13))
>this.attrs : Symbol(Test.attrs, Decl(strictNullNotNullIndexTypeNoLib.ts, 5, 25))
>this : Symbol(Test, Decl(strictNullNotNullIndexTypeNoLib.ts, 3, 1))
>attrs : Symbol(Test.attrs, Decl(strictNullNotNullIndexTypeNoLib.ts, 5, 25))
>params : Symbol(params, Decl(strictNullNotNullIndexTypeNoLib.ts, 1, 13))
>name : Symbol(name, Decl(strictNullNotNullIndexTypeNoLib.ts, 2, 14))
}
}
@@ -18,14 +18,14 @@ class Test<T extends A> {
>m : () => void
this.attrs.params!.name;
>this.attrs.params!.name : any
>this.attrs.params! : T["params"]
>this.attrs.params!.name : string
>this.attrs.params! : T["params"] & {}
>this.attrs.params : T["params"] | undefined
>this.attrs : Readonly<T>
>this : this
>attrs : Readonly<T>
>params : T["params"] | undefined
>name : any
>name : string
}
}
@@ -62,10 +62,10 @@ class Test2<T extends A> {
>attrs : Readonly<T>
m() {
>m : () => T["params"]
>m : () => T["params"] & {}
return this.attrs.params!; // Return type should maintain relationship with `T` after being not-null-asserted, ideally
>this.attrs.params! : T["params"]
>this.attrs.params! : T["params"] & {}
>this.attrs.params : T["params"] | undefined
>this.attrs : Readonly<T>
>this : this
@@ -653,7 +653,7 @@ function expectNotUndefined<T>(value: Undefinable<T>): T {
>'value is undefined' : "value is undefined"
}
return value;
>value : T
>value : T & ({} | null)
}
interface Bar {
@@ -54,7 +54,7 @@ type E = `${A & {}}`;
>E : "a"
type MixE = E & {}
>MixE : "a" & {}
>MixE : "a"
type OriginE = `${MixE}`
>OriginE : "a"
@@ -0,0 +1,313 @@
tests/cases/conformance/types/literal/templateLiteralTypes4.ts(285,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'.
tests/cases/conformance/types/literal/templateLiteralTypes4.ts(289,12): error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'.
==== tests/cases/conformance/types/literal/templateLiteralTypes4.ts (2 errors) ====
// infer from number
type TNumber0 = "100" extends `${infer N extends number}` ? N : never; // 100
type TNumber1 = "-100" extends `${infer N extends number}` ? N : never; // -100
type TNumber2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1
type TNumber3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008)
type TNumber4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
type TNumber5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
type TNumber6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
type TNumber7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
type TNumber8 = "abcd" extends `${infer N extends number}` ? N : never; // never
// infer from bigint
type TBigInt0 = "100" extends `${infer N extends bigint}` ? N : never; // 100n
type TBigInt1 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n
type TBigInt2 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable)
type TBigInt3 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable)
type TBigInt4 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable)
type TBigInt5 = "1.1" extends `${infer N extends bigint}` ? N : never; // never
type TBigInt6 = "10e2" extends `${infer N extends bigint}` ? N : never; // never
type TBigInt7 = "abcd" extends `${infer N extends bigint}` ? N : never; // never
// infer from boolean
type TBoolean0 = "true" extends `${infer T extends boolean}` ? T : never; // true
type TBoolean1 = "false" extends `${infer T extends boolean}` ? T : never; // false
type TBoolean2 = "abcd" extends `${infer T extends boolean}` ? T : never; // never
// infer from null
type TNull0 = "null" extends `${infer T extends null}` ? T : never; // null
type TNull1 = "abcd" extends `${infer T extends null}` ? T : never; // never
// infer from undefined
type TUndefined0 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined
type TUndefined1 = "abcd" extends `${infer T extends undefined}` ? T : never; // never
// infer from literal enums
const enum StringLiteralEnum { Zero = "0", True = "true", False = "false", Undefined = "undefined", Null = "null" }
type TStringLiteralEnum0 = "0" extends `${infer T extends StringLiteralEnum}` ? T : never; // StringLiteralEnum.Zero
const enum NumberLiteralEnum { Zero, One }
type TNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum}` ? T : never; // NumberLiteralEnum.Zero
// infer from non-literal enums
const enum NonLiteralEnum { Zero = NumberLiteralEnum.Zero, One = NumberLiteralEnum.One }
type TNonLiteralEnum0 = "0" extends `${infer T extends NonLiteralEnum}` ? T : never; // 0
// infer using priority:
// string > template-literal > (string-literal | string-literal-enum) >
// number > enum > (number-literal | number-literal-enum) >
// bigint > bigint-literal >
// boolean > (boolean-literal | undefined | null)
// #region string
// string > string-literal-enum
type PString00 = "0" extends `${infer T extends string | StringLiteralEnum}` ? T : never; // "0"
// string > number
type PString01 = "0" extends `${infer T extends string | number}` ? T : never; // "0"
// string > enum
type PString02 = "0" extends `${infer T extends string | NonLiteralEnum}` ? T : never; // "0"
// string > (number-literal | number-literal-enum)
type PString03 = "0" extends `${infer T extends string | 0}` ? T : never; // "0"
type PString04 = "0" extends `${infer T extends string | NumberLiteralEnum}` ? T : never; // "0"
// string > bigint
type PString05 = "0" extends `${infer T extends string | bigint}` ? T : never; // "0"
// string > bigint-literal
type PString06 = "0" extends `${infer T extends string | 0n}` ? T : never; // "0"
// string > boolean
type PString07 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true"
type PString08 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false"
// string > (boolean-literal | undefined | null)
type PString09 = "true" extends `${infer T extends string | true}` ? T : never; // "true"
type PString10 = "false" extends `${infer T extends string | false}` ? T : never; // "false"
type PString11 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined"
type PString12 = "null" extends `${infer T extends string | null}` ? T : never; // "null"
// #endregion string
// #region template-literal
// template-literal > number
type PTemplate00 = "10" extends `${infer T extends `1${string}` | number}` ? T : never; // "10"
// template-literal > enum
type PTemplate01 = "10" extends `${infer T extends `1${string}` | NonLiteralEnum}` ? T : never; // "10"
// template-literal > (number-literal | number-literal-enum)
type PTemplate02 = "10" extends `${infer T extends `1${string}` | 10}` ? T : never; // "10"
type PTemplate03 = "10" extends `${infer T extends `1${string}` | NumberLiteralEnum}` ? T : never; // "10"
// template-literal > bigint
type PTemplate04 = "10" extends `${infer T extends `1${string}` | bigint}` ? T : never; // "10"
// template-literal > bigint-literal
type PTemplate05 = "10" extends `${infer T extends `1${string}` | 10n}` ? T : never; // "10"
// template-literal > boolean
type PTemplate06 = "true" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "true"
type PTemplate07 = "false" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "false"
// template-literal > (boolean-literal | undefined | null)
type PTemplate08 = "true" extends `${infer T extends `${"t"}${string}` | true}` ? T : never; // "true"
type PTemplate09 = "false" extends `${infer T extends `${"f"}${string}` | false}` ? T : never; // "false"
type PTemplate10 = "undefined" extends `${infer T extends `${"u"}${string}` | undefined}` ? T : never; // "undefined"
type PTemplate11 = "null" extends `${infer T extends `${"n"}${string}` | null}` ? T : never; // "null"
// #endregion template-literal
// #region string-literal
// string-literal > number
type PStringLiteral00 = "0" extends `${infer T extends "0" | number}` ? T : never; // "0"
// string-literal > enum
type PStringLiteral01 = "0" extends `${infer T extends "0" | NonLiteralEnum}` ? T : never; // "0"
// string-literal > (number-literal | number-literal-enum)
type PStringLiteral02 = "0" extends `${infer T extends "0" | 0}` ? T : never; // "0"
type PStringLiteral03 = "0" extends `${infer T extends "0" | NumberLiteralEnum}` ? T : never; // "0"
// string-literal > bigint
type PStringLiteral04 = "0" extends `${infer T extends "0" | bigint}` ? T : never; // "0"
// string-literal > bigint-literal
type PStringLiteral05 = "0" extends `${infer T extends "0" | 0n}` ? T : never; // "0"
// string-literal > boolean
type PStringLiteral06 = "true" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "true"
type PStringLiteral07 = "false" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "false"
// string-literal > (boolean-literal | undefined | null)
type PStringLiteral08 = "true" extends `${infer T extends "true" | true}` ? T : never; // "true"
type PStringLiteral09 = "false" extends `${infer T extends "false" | false}` ? T : never; // "false"
type PStringLiteral10 = "undefined" extends `${infer T extends "undefined" | undefined}` ? T : never; // "undefined"
type PStringLiteral11 = "null" extends `${infer T extends "null" | null}` ? T : never; // "null"
// #endregion string-literal
// #region string-literal-enum
// string-literal-enum > number
type PStringLiteralEnum00 = "0" extends `${infer T extends StringLiteralEnum | number}` ? T : never; // StringLiteralEnum.Zero
// string-literal-enum > enum
type PStringLiteralEnum01 = "0" extends `${infer T extends StringLiteralEnum | NonLiteralEnum}` ? T : never; // StringLiteralEnum.Zero
// string-literal-enum > (number-literal | number-literal-enum)
type PStringLiteralEnum02 = "0" extends `${infer T extends StringLiteralEnum | 0}` ? T : never; // StringLiteralEnum.Zero
type PStringLiteralEnum03 = "0" extends `${infer T extends StringLiteralEnum | NumberLiteralEnum}` ? T : never; // StringLiteralEnum.Zero
// string-literal-enum > bigint
type PStringLiteralEnum04 = "0" extends `${infer T extends StringLiteralEnum | bigint}` ? T : never; // StringLiteralEnum.Zero
// string-literal-enum > bigint-literal
type PStringLiteralEnum05 = "0" extends `${infer T extends StringLiteralEnum | 0n}` ? T : never; // StringLiteralEnum.Zero
// string-literal-enum > boolean
type PStringLiteralEnum06 = "true" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.True
type PStringLiteralEnum07 = "false" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.False
// string-literal-enum > (boolean-literal | undefined | null)
type PStringLiteralEnum08 = "true" extends `${infer T extends StringLiteralEnum | true}` ? T : never; // StringLiteralEnum.True
type PStringLiteralEnum09 = "false" extends `${infer T extends StringLiteralEnum | false}` ? T : never; // StringLiteralEnum.False
type PStringLiteralEnum10 = "undefined" extends `${infer T extends StringLiteralEnum | undefined}` ? T : never; // StringLiteralEnum.Undefined
type PStringLiteralEnum11 = "null" extends `${infer T extends StringLiteralEnum | null}` ? T : never; // StringLiteralEnum.Null
// #endregion string-literal-enum
// #region number
// number > enum
type PNumber0 = "0" extends `${infer T extends number | NonLiteralEnum}` ? T : never; // 0
// number > number-literal-enum
type PNumber1 = "0" extends `${infer T extends number | NumberLiteralEnum}` ? T : never; // 0
// number > bigint
type PNumber2 = "0" extends `${infer T extends number | bigint}` ? T : never; // 0
// number > bigint-literal
type PNumber3 = "0" extends `${infer T extends number | 0n}` ? T : never; // 0
// #endregion number
// #region enum
// enum > number-literal-enum
type PEnum0 = "0" extends `${infer T extends NonLiteralEnum | NumberLiteralEnum}` ? T : never; // 0
// enum > bigint
type PEnum1 = "0" extends `${infer T extends NonLiteralEnum | bigint}` ? T : never; // 0
// enum > bigint-literal
type PEnum2 = "0" extends `${infer T extends NonLiteralEnum | 0n}` ? T : never; // 0
// #endregion enum
// #region number-literal
// number-literal > bigint
type PNumberLiteral0 = "0" extends `${infer T extends 0 | bigint}` ? T : never; // 0
// number-literal > bigint-literal
type PNumberLiteral1 = "0" extends `${infer T extends 0 | 0n}` ? T : never; // 0
// #endregion number-literal
// #region number-literal-enum
// number-literal-enum > bigint
type PNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum | bigint}` ? T : never; // NumberLiteralEnum.Zero
// number-literal-enum > bigint-literal
type PNumberLiteralEnum1 = "0" extends `${infer T extends NumberLiteralEnum | 0n}` ? T : never; // NumberLiteralEnum.Zero
// #endregion number-literal-enum
// non-matchable constituents are excluded
type PExclude0 = "0" extends `${infer T extends "1" | number}` ? T : never; // 0
type PExclude1 = "0" extends `${infer T extends `1${string}` | number}` ? T : never; // 0
type PExclude2 = "0" extends `${infer T extends 1 | bigint}` ? T : never; // 0n
type PExclude3 = "0" extends `${infer T extends NumberLiteralEnum.One | bigint}` ? T : never; // 0n
type PExclude4 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n
// infer to prefix from string
type TPrefix0 = "100" extends `${infer T extends number}${string}` ? T : never; // 1
type TPrefix1 = "trueabc" extends `${infer T extends boolean}${string}` ? T : never; // boolean (T only receives 't', not the whole string)
type TPrefix2 = `100:${string}` extends `${infer T extends number}:${string}` ? T : never; // 100 (T receives '100' because it scans until ':')
// can use union w/multiple branches to extract each possibility
type ExtractPrimitives<T extends string> =
| T
| (T extends `${infer U extends number}` ? U : never)
| (T extends `${infer U extends bigint}` ? U : never)
| (T extends `${infer U extends boolean | null | undefined}` ? U : never)
;
type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n
type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1
type TExtract2 = ExtractPrimitives<"true">; // "true" | true
// example use case (based on old TypedObjects proposal):
// Use constrained `infer` in template literal to get ordinal indices as numbers:
type IndexFor<S extends string> = S extends `${infer N extends number}` ? N : never;
type IndicesOf<T> = IndexFor<Extract<keyof T, string>>; // ordinal indices as number literals
interface FieldDefinition {
readonly name: string;
readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64";
}
type FieldType<T extends FieldDefinition["type"]> =
T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number :
T extends "f32" | "f64" ? bigint :
never;
// Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]`
type TypedObjectNamedMembers<TDef extends readonly FieldDefinition[]> = {
[P in TDef[number]["name"]]: FieldType<Extract<TDef[number], { readonly name: P }>["type"]>;
};
// Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]`
type TypedObjectOrdinalMembers<TDef extends readonly FieldDefinition[]> = {
[I in Extract<keyof TDef, `${number}`>]: FieldType<Extract<TDef[I], FieldDefinition>["type"]>;
};
// Default members
interface TypedObjectMembers<TDef extends readonly FieldDefinition[]> {
// get/set a field by name
get<K extends TDef[number]["name"]>(key: K): FieldType<Extract<TDef[number], { readonly name: K }>["type"]>;
set<K extends TDef[number]["name"]>(key: K, value: FieldType<Extract<TDef[number], { readonly name: K }>["type"]>): void;
// get/set a field by index
getIndex<I extends IndicesOf<TDef>>(index: I): FieldType<Extract<TDef[I], FieldDefinition>["type"]>;
setIndex<I extends IndicesOf<TDef>>(index: I, value: FieldType<Extract<TDef[I], FieldDefinition>["type"]>): void;
}
type TypedObject<TDef extends readonly FieldDefinition[]> =
& TypedObjectMembers<TDef>
& TypedObjectNamedMembers<TDef>
& TypedObjectOrdinalMembers<TDef>;
// NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type
type Point = TypedObject<[
{ name: "x", type: "f64" },
{ name: "y", type: "f64" },
]>;
declare const p: Point;
p.getIndex(0); // ok, 0 is a valid index
p.getIndex(1); // ok, 1 is a valid index
p.getIndex(2); // error, 2 is not a valid index
~
!!! error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'.
p.setIndex(0, 0); // ok, 0 is a valid index
p.setIndex(1, 0); // ok, 1 is a valid index
p.setIndex(2, 3); // error, 2 is not a valid index
~
!!! error TS2345: Argument of type '2' is not assignable to parameter of type '0 | 1'.
// function inference
declare function f1<T extends string | number>(s: `**${T}**`): T;
f1("**123**"); // "123"
declare function f2<T extends number>(s: `**${T}**`): T;
f2("**123**"); // 123
declare function f3<T extends bigint>(s: `**${T}**`): T;
f3("**123**"); // 123n
declare function f4<T extends boolean>(s: `**${T}**`): T;
f4("**true**"); // true | "true"
f4("**false**"); // false | "false"
@@ -0,0 +1,477 @@
//// [templateLiteralTypes4.ts]
// infer from number
type TNumber0 = "100" extends `${infer N extends number}` ? N : never; // 100
type TNumber1 = "-100" extends `${infer N extends number}` ? N : never; // -100
type TNumber2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1
type TNumber3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008)
type TNumber4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
type TNumber5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
type TNumber6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
type TNumber7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
type TNumber8 = "abcd" extends `${infer N extends number}` ? N : never; // never
// infer from bigint
type TBigInt0 = "100" extends `${infer N extends bigint}` ? N : never; // 100n
type TBigInt1 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n
type TBigInt2 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable)
type TBigInt3 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable)
type TBigInt4 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable)
type TBigInt5 = "1.1" extends `${infer N extends bigint}` ? N : never; // never
type TBigInt6 = "10e2" extends `${infer N extends bigint}` ? N : never; // never
type TBigInt7 = "abcd" extends `${infer N extends bigint}` ? N : never; // never
// infer from boolean
type TBoolean0 = "true" extends `${infer T extends boolean}` ? T : never; // true
type TBoolean1 = "false" extends `${infer T extends boolean}` ? T : never; // false
type TBoolean2 = "abcd" extends `${infer T extends boolean}` ? T : never; // never
// infer from null
type TNull0 = "null" extends `${infer T extends null}` ? T : never; // null
type TNull1 = "abcd" extends `${infer T extends null}` ? T : never; // never
// infer from undefined
type TUndefined0 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined
type TUndefined1 = "abcd" extends `${infer T extends undefined}` ? T : never; // never
// infer from literal enums
const enum StringLiteralEnum { Zero = "0", True = "true", False = "false", Undefined = "undefined", Null = "null" }
type TStringLiteralEnum0 = "0" extends `${infer T extends StringLiteralEnum}` ? T : never; // StringLiteralEnum.Zero
const enum NumberLiteralEnum { Zero, One }
type TNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum}` ? T : never; // NumberLiteralEnum.Zero
// infer from non-literal enums
const enum NonLiteralEnum { Zero = NumberLiteralEnum.Zero, One = NumberLiteralEnum.One }
type TNonLiteralEnum0 = "0" extends `${infer T extends NonLiteralEnum}` ? T : never; // 0
// infer using priority:
// string > template-literal > (string-literal | string-literal-enum) >
// number > enum > (number-literal | number-literal-enum) >
// bigint > bigint-literal >
// boolean > (boolean-literal | undefined | null)
// #region string
// string > string-literal-enum
type PString00 = "0" extends `${infer T extends string | StringLiteralEnum}` ? T : never; // "0"
// string > number
type PString01 = "0" extends `${infer T extends string | number}` ? T : never; // "0"
// string > enum
type PString02 = "0" extends `${infer T extends string | NonLiteralEnum}` ? T : never; // "0"
// string > (number-literal | number-literal-enum)
type PString03 = "0" extends `${infer T extends string | 0}` ? T : never; // "0"
type PString04 = "0" extends `${infer T extends string | NumberLiteralEnum}` ? T : never; // "0"
// string > bigint
type PString05 = "0" extends `${infer T extends string | bigint}` ? T : never; // "0"
// string > bigint-literal
type PString06 = "0" extends `${infer T extends string | 0n}` ? T : never; // "0"
// string > boolean
type PString07 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true"
type PString08 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false"
// string > (boolean-literal | undefined | null)
type PString09 = "true" extends `${infer T extends string | true}` ? T : never; // "true"
type PString10 = "false" extends `${infer T extends string | false}` ? T : never; // "false"
type PString11 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined"
type PString12 = "null" extends `${infer T extends string | null}` ? T : never; // "null"
// #endregion string
// #region template-literal
// template-literal > number
type PTemplate00 = "10" extends `${infer T extends `1${string}` | number}` ? T : never; // "10"
// template-literal > enum
type PTemplate01 = "10" extends `${infer T extends `1${string}` | NonLiteralEnum}` ? T : never; // "10"
// template-literal > (number-literal | number-literal-enum)
type PTemplate02 = "10" extends `${infer T extends `1${string}` | 10}` ? T : never; // "10"
type PTemplate03 = "10" extends `${infer T extends `1${string}` | NumberLiteralEnum}` ? T : never; // "10"
// template-literal > bigint
type PTemplate04 = "10" extends `${infer T extends `1${string}` | bigint}` ? T : never; // "10"
// template-literal > bigint-literal
type PTemplate05 = "10" extends `${infer T extends `1${string}` | 10n}` ? T : never; // "10"
// template-literal > boolean
type PTemplate06 = "true" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "true"
type PTemplate07 = "false" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "false"
// template-literal > (boolean-literal | undefined | null)
type PTemplate08 = "true" extends `${infer T extends `${"t"}${string}` | true}` ? T : never; // "true"
type PTemplate09 = "false" extends `${infer T extends `${"f"}${string}` | false}` ? T : never; // "false"
type PTemplate10 = "undefined" extends `${infer T extends `${"u"}${string}` | undefined}` ? T : never; // "undefined"
type PTemplate11 = "null" extends `${infer T extends `${"n"}${string}` | null}` ? T : never; // "null"
// #endregion template-literal
// #region string-literal
// string-literal > number
type PStringLiteral00 = "0" extends `${infer T extends "0" | number}` ? T : never; // "0"
// string-literal > enum
type PStringLiteral01 = "0" extends `${infer T extends "0" | NonLiteralEnum}` ? T : never; // "0"
// string-literal > (number-literal | number-literal-enum)
type PStringLiteral02 = "0" extends `${infer T extends "0" | 0}` ? T : never; // "0"
type PStringLiteral03 = "0" extends `${infer T extends "0" | NumberLiteralEnum}` ? T : never; // "0"
// string-literal > bigint
type PStringLiteral04 = "0" extends `${infer T extends "0" | bigint}` ? T : never; // "0"
// string-literal > bigint-literal
type PStringLiteral05 = "0" extends `${infer T extends "0" | 0n}` ? T : never; // "0"
// string-literal > boolean
type PStringLiteral06 = "true" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "true"
type PStringLiteral07 = "false" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "false"
// string-literal > (boolean-literal | undefined | null)
type PStringLiteral08 = "true" extends `${infer T extends "true" | true}` ? T : never; // "true"
type PStringLiteral09 = "false" extends `${infer T extends "false" | false}` ? T : never; // "false"
type PStringLiteral10 = "undefined" extends `${infer T extends "undefined" | undefined}` ? T : never; // "undefined"
type PStringLiteral11 = "null" extends `${infer T extends "null" | null}` ? T : never; // "null"
// #endregion string-literal
// #region string-literal-enum
// string-literal-enum > number
type PStringLiteralEnum00 = "0" extends `${infer T extends StringLiteralEnum | number}` ? T : never; // StringLiteralEnum.Zero
// string-literal-enum > enum
type PStringLiteralEnum01 = "0" extends `${infer T extends StringLiteralEnum | NonLiteralEnum}` ? T : never; // StringLiteralEnum.Zero
// string-literal-enum > (number-literal | number-literal-enum)
type PStringLiteralEnum02 = "0" extends `${infer T extends StringLiteralEnum | 0}` ? T : never; // StringLiteralEnum.Zero
type PStringLiteralEnum03 = "0" extends `${infer T extends StringLiteralEnum | NumberLiteralEnum}` ? T : never; // StringLiteralEnum.Zero
// string-literal-enum > bigint
type PStringLiteralEnum04 = "0" extends `${infer T extends StringLiteralEnum | bigint}` ? T : never; // StringLiteralEnum.Zero
// string-literal-enum > bigint-literal
type PStringLiteralEnum05 = "0" extends `${infer T extends StringLiteralEnum | 0n}` ? T : never; // StringLiteralEnum.Zero
// string-literal-enum > boolean
type PStringLiteralEnum06 = "true" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.True
type PStringLiteralEnum07 = "false" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.False
// string-literal-enum > (boolean-literal | undefined | null)
type PStringLiteralEnum08 = "true" extends `${infer T extends StringLiteralEnum | true}` ? T : never; // StringLiteralEnum.True
type PStringLiteralEnum09 = "false" extends `${infer T extends StringLiteralEnum | false}` ? T : never; // StringLiteralEnum.False
type PStringLiteralEnum10 = "undefined" extends `${infer T extends StringLiteralEnum | undefined}` ? T : never; // StringLiteralEnum.Undefined
type PStringLiteralEnum11 = "null" extends `${infer T extends StringLiteralEnum | null}` ? T : never; // StringLiteralEnum.Null
// #endregion string-literal-enum
// #region number
// number > enum
type PNumber0 = "0" extends `${infer T extends number | NonLiteralEnum}` ? T : never; // 0
// number > number-literal-enum
type PNumber1 = "0" extends `${infer T extends number | NumberLiteralEnum}` ? T : never; // 0
// number > bigint
type PNumber2 = "0" extends `${infer T extends number | bigint}` ? T : never; // 0
// number > bigint-literal
type PNumber3 = "0" extends `${infer T extends number | 0n}` ? T : never; // 0
// #endregion number
// #region enum
// enum > number-literal-enum
type PEnum0 = "0" extends `${infer T extends NonLiteralEnum | NumberLiteralEnum}` ? T : never; // 0
// enum > bigint
type PEnum1 = "0" extends `${infer T extends NonLiteralEnum | bigint}` ? T : never; // 0
// enum > bigint-literal
type PEnum2 = "0" extends `${infer T extends NonLiteralEnum | 0n}` ? T : never; // 0
// #endregion enum
// #region number-literal
// number-literal > bigint
type PNumberLiteral0 = "0" extends `${infer T extends 0 | bigint}` ? T : never; // 0
// number-literal > bigint-literal
type PNumberLiteral1 = "0" extends `${infer T extends 0 | 0n}` ? T : never; // 0
// #endregion number-literal
// #region number-literal-enum
// number-literal-enum > bigint
type PNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum | bigint}` ? T : never; // NumberLiteralEnum.Zero
// number-literal-enum > bigint-literal
type PNumberLiteralEnum1 = "0" extends `${infer T extends NumberLiteralEnum | 0n}` ? T : never; // NumberLiteralEnum.Zero
// #endregion number-literal-enum
// non-matchable constituents are excluded
type PExclude0 = "0" extends `${infer T extends "1" | number}` ? T : never; // 0
type PExclude1 = "0" extends `${infer T extends `1${string}` | number}` ? T : never; // 0
type PExclude2 = "0" extends `${infer T extends 1 | bigint}` ? T : never; // 0n
type PExclude3 = "0" extends `${infer T extends NumberLiteralEnum.One | bigint}` ? T : never; // 0n
type PExclude4 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n
// infer to prefix from string
type TPrefix0 = "100" extends `${infer T extends number}${string}` ? T : never; // 1
type TPrefix1 = "trueabc" extends `${infer T extends boolean}${string}` ? T : never; // boolean (T only receives 't', not the whole string)
type TPrefix2 = `100:${string}` extends `${infer T extends number}:${string}` ? T : never; // 100 (T receives '100' because it scans until ':')
// can use union w/multiple branches to extract each possibility
type ExtractPrimitives<T extends string> =
| T
| (T extends `${infer U extends number}` ? U : never)
| (T extends `${infer U extends bigint}` ? U : never)
| (T extends `${infer U extends boolean | null | undefined}` ? U : never)
;
type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n
type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1
type TExtract2 = ExtractPrimitives<"true">; // "true" | true
// example use case (based on old TypedObjects proposal):
// Use constrained `infer` in template literal to get ordinal indices as numbers:
type IndexFor<S extends string> = S extends `${infer N extends number}` ? N : never;
type IndicesOf<T> = IndexFor<Extract<keyof T, string>>; // ordinal indices as number literals
interface FieldDefinition {
readonly name: string;
readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64";
}
type FieldType<T extends FieldDefinition["type"]> =
T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number :
T extends "f32" | "f64" ? bigint :
never;
// Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]`
type TypedObjectNamedMembers<TDef extends readonly FieldDefinition[]> = {
[P in TDef[number]["name"]]: FieldType<Extract<TDef[number], { readonly name: P }>["type"]>;
};
// Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]`
type TypedObjectOrdinalMembers<TDef extends readonly FieldDefinition[]> = {
[I in Extract<keyof TDef, `${number}`>]: FieldType<Extract<TDef[I], FieldDefinition>["type"]>;
};
// Default members
interface TypedObjectMembers<TDef extends readonly FieldDefinition[]> {
// get/set a field by name
get<K extends TDef[number]["name"]>(key: K): FieldType<Extract<TDef[number], { readonly name: K }>["type"]>;
set<K extends TDef[number]["name"]>(key: K, value: FieldType<Extract<TDef[number], { readonly name: K }>["type"]>): void;
// get/set a field by index
getIndex<I extends IndicesOf<TDef>>(index: I): FieldType<Extract<TDef[I], FieldDefinition>["type"]>;
setIndex<I extends IndicesOf<TDef>>(index: I, value: FieldType<Extract<TDef[I], FieldDefinition>["type"]>): void;
}
type TypedObject<TDef extends readonly FieldDefinition[]> =
& TypedObjectMembers<TDef>
& TypedObjectNamedMembers<TDef>
& TypedObjectOrdinalMembers<TDef>;
// NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type
type Point = TypedObject<[
{ name: "x", type: "f64" },
{ name: "y", type: "f64" },
]>;
declare const p: Point;
p.getIndex(0); // ok, 0 is a valid index
p.getIndex(1); // ok, 1 is a valid index
p.getIndex(2); // error, 2 is not a valid index
p.setIndex(0, 0); // ok, 0 is a valid index
p.setIndex(1, 0); // ok, 1 is a valid index
p.setIndex(2, 3); // error, 2 is not a valid index
// function inference
declare function f1<T extends string | number>(s: `**${T}**`): T;
f1("**123**"); // "123"
declare function f2<T extends number>(s: `**${T}**`): T;
f2("**123**"); // 123
declare function f3<T extends bigint>(s: `**${T}**`): T;
f3("**123**"); // 123n
declare function f4<T extends boolean>(s: `**${T}**`): T;
f4("**true**"); // true | "true"
f4("**false**"); // false | "false"
//// [templateLiteralTypes4.js]
"use strict";
p.getIndex(0); // ok, 0 is a valid index
p.getIndex(1); // ok, 1 is a valid index
p.getIndex(2); // error, 2 is not a valid index
p.setIndex(0, 0); // ok, 0 is a valid index
p.setIndex(1, 0); // ok, 1 is a valid index
p.setIndex(2, 3); // error, 2 is not a valid index
f1("**123**"); // "123"
f2("**123**"); // 123
f3("**123**"); // 123n
f4("**true**"); // true | "true"
f4("**false**"); // false | "false"
//// [templateLiteralTypes4.d.ts]
declare type TNumber0 = "100" extends `${infer N extends number}` ? N : never;
declare type TNumber1 = "-100" extends `${infer N extends number}` ? N : never;
declare type TNumber2 = "1.1" extends `${infer N extends number}` ? N : never;
declare type TNumber3 = "8e-11" extends `${infer N extends number}` ? N : never;
declare type TNumber4 = "0x10" extends `${infer N extends number}` ? N : never;
declare type TNumber5 = "0o10" extends `${infer N extends number}` ? N : never;
declare type TNumber6 = "0b10" extends `${infer N extends number}` ? N : never;
declare type TNumber7 = "10e2" extends `${infer N extends number}` ? N : never;
declare type TNumber8 = "abcd" extends `${infer N extends number}` ? N : never;
declare type TBigInt0 = "100" extends `${infer N extends bigint}` ? N : never;
declare type TBigInt1 = "-100" extends `${infer N extends bigint}` ? N : never;
declare type TBigInt2 = "0x10" extends `${infer N extends bigint}` ? N : never;
declare type TBigInt3 = "0o10" extends `${infer N extends bigint}` ? N : never;
declare type TBigInt4 = "0b10" extends `${infer N extends bigint}` ? N : never;
declare type TBigInt5 = "1.1" extends `${infer N extends bigint}` ? N : never;
declare type TBigInt6 = "10e2" extends `${infer N extends bigint}` ? N : never;
declare type TBigInt7 = "abcd" extends `${infer N extends bigint}` ? N : never;
declare type TBoolean0 = "true" extends `${infer T extends boolean}` ? T : never;
declare type TBoolean1 = "false" extends `${infer T extends boolean}` ? T : never;
declare type TBoolean2 = "abcd" extends `${infer T extends boolean}` ? T : never;
declare type TNull0 = "null" extends `${infer T extends null}` ? T : never;
declare type TNull1 = "abcd" extends `${infer T extends null}` ? T : never;
declare type TUndefined0 = "undefined" extends `${infer T extends undefined}` ? T : never;
declare type TUndefined1 = "abcd" extends `${infer T extends undefined}` ? T : never;
declare const enum StringLiteralEnum {
Zero = "0",
True = "true",
False = "false",
Undefined = "undefined",
Null = "null"
}
declare type TStringLiteralEnum0 = "0" extends `${infer T extends StringLiteralEnum}` ? T : never;
declare const enum NumberLiteralEnum {
Zero = 0,
One = 1
}
declare type TNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum}` ? T : never;
declare const enum NonLiteralEnum {
Zero = 0,
One = 1
}
declare type TNonLiteralEnum0 = "0" extends `${infer T extends NonLiteralEnum}` ? T : never;
declare type PString00 = "0" extends `${infer T extends string | StringLiteralEnum}` ? T : never;
declare type PString01 = "0" extends `${infer T extends string | number}` ? T : never;
declare type PString02 = "0" extends `${infer T extends string | NonLiteralEnum}` ? T : never;
declare type PString03 = "0" extends `${infer T extends string | 0}` ? T : never;
declare type PString04 = "0" extends `${infer T extends string | NumberLiteralEnum}` ? T : never;
declare type PString05 = "0" extends `${infer T extends string | bigint}` ? T : never;
declare type PString06 = "0" extends `${infer T extends string | 0n}` ? T : never;
declare type PString07 = "true" extends `${infer T extends string | boolean}` ? T : never;
declare type PString08 = "false" extends `${infer T extends string | boolean}` ? T : never;
declare type PString09 = "true" extends `${infer T extends string | true}` ? T : never;
declare type PString10 = "false" extends `${infer T extends string | false}` ? T : never;
declare type PString11 = "undefined" extends `${infer T extends string | undefined}` ? T : never;
declare type PString12 = "null" extends `${infer T extends string | null}` ? T : never;
declare type PTemplate00 = "10" extends `${infer T extends `1${string}` | number}` ? T : never;
declare type PTemplate01 = "10" extends `${infer T extends `1${string}` | NonLiteralEnum}` ? T : never;
declare type PTemplate02 = "10" extends `${infer T extends `1${string}` | 10}` ? T : never;
declare type PTemplate03 = "10" extends `${infer T extends `1${string}` | NumberLiteralEnum}` ? T : never;
declare type PTemplate04 = "10" extends `${infer T extends `1${string}` | bigint}` ? T : never;
declare type PTemplate05 = "10" extends `${infer T extends `1${string}` | 10n}` ? T : never;
declare type PTemplate06 = "true" extends `${infer T extends `${string}e` | boolean}` ? T : never;
declare type PTemplate07 = "false" extends `${infer T extends `${string}e` | boolean}` ? T : never;
declare type PTemplate08 = "true" extends `${infer T extends `${"t"}${string}` | true}` ? T : never;
declare type PTemplate09 = "false" extends `${infer T extends `${"f"}${string}` | false}` ? T : never;
declare type PTemplate10 = "undefined" extends `${infer T extends `${"u"}${string}` | undefined}` ? T : never;
declare type PTemplate11 = "null" extends `${infer T extends `${"n"}${string}` | null}` ? T : never;
declare type PStringLiteral00 = "0" extends `${infer T extends "0" | number}` ? T : never;
declare type PStringLiteral01 = "0" extends `${infer T extends "0" | NonLiteralEnum}` ? T : never;
declare type PStringLiteral02 = "0" extends `${infer T extends "0" | 0}` ? T : never;
declare type PStringLiteral03 = "0" extends `${infer T extends "0" | NumberLiteralEnum}` ? T : never;
declare type PStringLiteral04 = "0" extends `${infer T extends "0" | bigint}` ? T : never;
declare type PStringLiteral05 = "0" extends `${infer T extends "0" | 0n}` ? T : never;
declare type PStringLiteral06 = "true" extends `${infer T extends "true" | "false" | boolean}` ? T : never;
declare type PStringLiteral07 = "false" extends `${infer T extends "true" | "false" | boolean}` ? T : never;
declare type PStringLiteral08 = "true" extends `${infer T extends "true" | true}` ? T : never;
declare type PStringLiteral09 = "false" extends `${infer T extends "false" | false}` ? T : never;
declare type PStringLiteral10 = "undefined" extends `${infer T extends "undefined" | undefined}` ? T : never;
declare type PStringLiteral11 = "null" extends `${infer T extends "null" | null}` ? T : never;
declare type PStringLiteralEnum00 = "0" extends `${infer T extends StringLiteralEnum | number}` ? T : never;
declare type PStringLiteralEnum01 = "0" extends `${infer T extends StringLiteralEnum | NonLiteralEnum}` ? T : never;
declare type PStringLiteralEnum02 = "0" extends `${infer T extends StringLiteralEnum | 0}` ? T : never;
declare type PStringLiteralEnum03 = "0" extends `${infer T extends StringLiteralEnum | NumberLiteralEnum}` ? T : never;
declare type PStringLiteralEnum04 = "0" extends `${infer T extends StringLiteralEnum | bigint}` ? T : never;
declare type PStringLiteralEnum05 = "0" extends `${infer T extends StringLiteralEnum | 0n}` ? T : never;
declare type PStringLiteralEnum06 = "true" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never;
declare type PStringLiteralEnum07 = "false" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never;
declare type PStringLiteralEnum08 = "true" extends `${infer T extends StringLiteralEnum | true}` ? T : never;
declare type PStringLiteralEnum09 = "false" extends `${infer T extends StringLiteralEnum | false}` ? T : never;
declare type PStringLiteralEnum10 = "undefined" extends `${infer T extends StringLiteralEnum | undefined}` ? T : never;
declare type PStringLiteralEnum11 = "null" extends `${infer T extends StringLiteralEnum | null}` ? T : never;
declare type PNumber0 = "0" extends `${infer T extends number | NonLiteralEnum}` ? T : never;
declare type PNumber1 = "0" extends `${infer T extends number | NumberLiteralEnum}` ? T : never;
declare type PNumber2 = "0" extends `${infer T extends number | bigint}` ? T : never;
declare type PNumber3 = "0" extends `${infer T extends number | 0n}` ? T : never;
declare type PEnum0 = "0" extends `${infer T extends NonLiteralEnum | NumberLiteralEnum}` ? T : never;
declare type PEnum1 = "0" extends `${infer T extends NonLiteralEnum | bigint}` ? T : never;
declare type PEnum2 = "0" extends `${infer T extends NonLiteralEnum | 0n}` ? T : never;
declare type PNumberLiteral0 = "0" extends `${infer T extends 0 | bigint}` ? T : never;
declare type PNumberLiteral1 = "0" extends `${infer T extends 0 | 0n}` ? T : never;
declare type PNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum | bigint}` ? T : never;
declare type PNumberLiteralEnum1 = "0" extends `${infer T extends NumberLiteralEnum | 0n}` ? T : never;
declare type PExclude0 = "0" extends `${infer T extends "1" | number}` ? T : never;
declare type PExclude1 = "0" extends `${infer T extends `1${string}` | number}` ? T : never;
declare type PExclude2 = "0" extends `${infer T extends 1 | bigint}` ? T : never;
declare type PExclude3 = "0" extends `${infer T extends NumberLiteralEnum.One | bigint}` ? T : never;
declare type PExclude4 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never;
declare type TPrefix0 = "100" extends `${infer T extends number}${string}` ? T : never;
declare type TPrefix1 = "trueabc" extends `${infer T extends boolean}${string}` ? T : never;
declare type TPrefix2 = `100:${string}` extends `${infer T extends number}:${string}` ? T : never;
declare type ExtractPrimitives<T extends string> = T | (T extends `${infer U extends number}` ? U : never) | (T extends `${infer U extends bigint}` ? U : never) | (T extends `${infer U extends boolean | null | undefined}` ? U : never);
declare type TExtract0 = ExtractPrimitives<"100">;
declare type TExtract1 = ExtractPrimitives<"1.1">;
declare type TExtract2 = ExtractPrimitives<"true">;
declare type IndexFor<S extends string> = S extends `${infer N extends number}` ? N : never;
declare type IndicesOf<T> = IndexFor<Extract<keyof T, string>>;
interface FieldDefinition {
readonly name: string;
readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64";
}
declare type FieldType<T extends FieldDefinition["type"]> = T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number : T extends "f32" | "f64" ? bigint : never;
declare type TypedObjectNamedMembers<TDef extends readonly FieldDefinition[]> = {
[P in TDef[number]["name"]]: FieldType<Extract<TDef[number], {
readonly name: P;
}>["type"]>;
};
declare type TypedObjectOrdinalMembers<TDef extends readonly FieldDefinition[]> = {
[I in Extract<keyof TDef, `${number}`>]: FieldType<Extract<TDef[I], FieldDefinition>["type"]>;
};
interface TypedObjectMembers<TDef extends readonly FieldDefinition[]> {
get<K extends TDef[number]["name"]>(key: K): FieldType<Extract<TDef[number], {
readonly name: K;
}>["type"]>;
set<K extends TDef[number]["name"]>(key: K, value: FieldType<Extract<TDef[number], {
readonly name: K;
}>["type"]>): void;
getIndex<I extends IndicesOf<TDef>>(index: I): FieldType<Extract<TDef[I], FieldDefinition>["type"]>;
setIndex<I extends IndicesOf<TDef>>(index: I, value: FieldType<Extract<TDef[I], FieldDefinition>["type"]>): void;
}
declare type TypedObject<TDef extends readonly FieldDefinition[]> = TypedObjectMembers<TDef> & TypedObjectNamedMembers<TDef> & TypedObjectOrdinalMembers<TDef>;
declare type Point = TypedObject<[
{
name: "x";
type: "f64";
},
{
name: "y";
type: "f64";
}
]>;
declare const p: Point;
declare function f1<T extends string | number>(s: `**${T}**`): T;
declare function f2<T extends number>(s: `**${T}**`): T;
declare function f3<T extends bigint>(s: `**${T}**`): T;
declare function f4<T extends boolean>(s: `**${T}**`): T;
@@ -0,0 +1,898 @@
=== tests/cases/conformance/types/literal/templateLiteralTypes4.ts ===
// infer from number
type TNumber0 = "100" extends `${infer N extends number}` ? N : never; // 100
>TNumber0 : Symbol(TNumber0, Decl(templateLiteralTypes4.ts, 0, 0))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 1, 38))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 1, 38))
type TNumber1 = "-100" extends `${infer N extends number}` ? N : never; // -100
>TNumber1 : Symbol(TNumber1, Decl(templateLiteralTypes4.ts, 1, 70))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 2, 39))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 2, 39))
type TNumber2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1
>TNumber2 : Symbol(TNumber2, Decl(templateLiteralTypes4.ts, 2, 71))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 3, 38))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 3, 38))
type TNumber3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008)
>TNumber3 : Symbol(TNumber3, Decl(templateLiteralTypes4.ts, 3, 70))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 4, 40))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 4, 40))
type TNumber4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
>TNumber4 : Symbol(TNumber4, Decl(templateLiteralTypes4.ts, 4, 72))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 5, 39))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 5, 39))
type TNumber5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
>TNumber5 : Symbol(TNumber5, Decl(templateLiteralTypes4.ts, 5, 71))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 6, 39))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 6, 39))
type TNumber6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
>TNumber6 : Symbol(TNumber6, Decl(templateLiteralTypes4.ts, 6, 71))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 7, 39))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 7, 39))
type TNumber7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
>TNumber7 : Symbol(TNumber7, Decl(templateLiteralTypes4.ts, 7, 71))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 8, 39))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 8, 39))
type TNumber8 = "abcd" extends `${infer N extends number}` ? N : never; // never
>TNumber8 : Symbol(TNumber8, Decl(templateLiteralTypes4.ts, 8, 71))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 9, 39))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 9, 39))
// infer from bigint
type TBigInt0 = "100" extends `${infer N extends bigint}` ? N : never; // 100n
>TBigInt0 : Symbol(TBigInt0, Decl(templateLiteralTypes4.ts, 9, 71))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 12, 38))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 12, 38))
type TBigInt1 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n
>TBigInt1 : Symbol(TBigInt1, Decl(templateLiteralTypes4.ts, 12, 70))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 13, 39))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 13, 39))
type TBigInt2 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable)
>TBigInt2 : Symbol(TBigInt2, Decl(templateLiteralTypes4.ts, 13, 71))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 14, 39))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 14, 39))
type TBigInt3 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable)
>TBigInt3 : Symbol(TBigInt3, Decl(templateLiteralTypes4.ts, 14, 71))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 15, 39))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 15, 39))
type TBigInt4 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable)
>TBigInt4 : Symbol(TBigInt4, Decl(templateLiteralTypes4.ts, 15, 71))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 16, 39))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 16, 39))
type TBigInt5 = "1.1" extends `${infer N extends bigint}` ? N : never; // never
>TBigInt5 : Symbol(TBigInt5, Decl(templateLiteralTypes4.ts, 16, 71))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 17, 38))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 17, 38))
type TBigInt6 = "10e2" extends `${infer N extends bigint}` ? N : never; // never
>TBigInt6 : Symbol(TBigInt6, Decl(templateLiteralTypes4.ts, 17, 70))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 18, 39))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 18, 39))
type TBigInt7 = "abcd" extends `${infer N extends bigint}` ? N : never; // never
>TBigInt7 : Symbol(TBigInt7, Decl(templateLiteralTypes4.ts, 18, 71))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 19, 39))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 19, 39))
// infer from boolean
type TBoolean0 = "true" extends `${infer T extends boolean}` ? T : never; // true
>TBoolean0 : Symbol(TBoolean0, Decl(templateLiteralTypes4.ts, 19, 71))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 22, 40))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 22, 40))
type TBoolean1 = "false" extends `${infer T extends boolean}` ? T : never; // false
>TBoolean1 : Symbol(TBoolean1, Decl(templateLiteralTypes4.ts, 22, 73))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 23, 41))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 23, 41))
type TBoolean2 = "abcd" extends `${infer T extends boolean}` ? T : never; // never
>TBoolean2 : Symbol(TBoolean2, Decl(templateLiteralTypes4.ts, 23, 74))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 24, 40))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 24, 40))
// infer from null
type TNull0 = "null" extends `${infer T extends null}` ? T : never; // null
>TNull0 : Symbol(TNull0, Decl(templateLiteralTypes4.ts, 24, 73))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 27, 37))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 27, 37))
type TNull1 = "abcd" extends `${infer T extends null}` ? T : never; // never
>TNull1 : Symbol(TNull1, Decl(templateLiteralTypes4.ts, 27, 67))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 28, 37))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 28, 37))
// infer from undefined
type TUndefined0 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined
>TUndefined0 : Symbol(TUndefined0, Decl(templateLiteralTypes4.ts, 28, 67))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 47))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 31, 47))
type TUndefined1 = "abcd" extends `${infer T extends undefined}` ? T : never; // never
>TUndefined1 : Symbol(TUndefined1, Decl(templateLiteralTypes4.ts, 31, 82))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 42))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 32, 42))
// infer from literal enums
const enum StringLiteralEnum { Zero = "0", True = "true", False = "false", Undefined = "undefined", Null = "null" }
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>Zero : Symbol(StringLiteralEnum.Zero, Decl(templateLiteralTypes4.ts, 35, 30))
>True : Symbol(StringLiteralEnum.True, Decl(templateLiteralTypes4.ts, 35, 42))
>False : Symbol(StringLiteralEnum.False, Decl(templateLiteralTypes4.ts, 35, 57))
>Undefined : Symbol(StringLiteralEnum.Undefined, Decl(templateLiteralTypes4.ts, 35, 74))
>Null : Symbol(StringLiteralEnum.Null, Decl(templateLiteralTypes4.ts, 35, 99))
type TStringLiteralEnum0 = "0" extends `${infer T extends StringLiteralEnum}` ? T : never; // StringLiteralEnum.Zero
>TStringLiteralEnum0 : Symbol(TStringLiteralEnum0, Decl(templateLiteralTypes4.ts, 35, 115))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 36, 47))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 36, 47))
const enum NumberLiteralEnum { Zero, One }
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>Zero : Symbol(NumberLiteralEnum.Zero, Decl(templateLiteralTypes4.ts, 38, 30))
>One : Symbol(NumberLiteralEnum.One, Decl(templateLiteralTypes4.ts, 38, 36))
type TNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum}` ? T : never; // NumberLiteralEnum.Zero
>TNumberLiteralEnum0 : Symbol(TNumberLiteralEnum0, Decl(templateLiteralTypes4.ts, 38, 42))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 39, 47))
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 39, 47))
// infer from non-literal enums
const enum NonLiteralEnum { Zero = NumberLiteralEnum.Zero, One = NumberLiteralEnum.One }
>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90))
>Zero : Symbol(NonLiteralEnum.Zero, Decl(templateLiteralTypes4.ts, 42, 27))
>NumberLiteralEnum.Zero : Symbol(NumberLiteralEnum.Zero, Decl(templateLiteralTypes4.ts, 38, 30))
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>Zero : Symbol(NumberLiteralEnum.Zero, Decl(templateLiteralTypes4.ts, 38, 30))
>One : Symbol(NonLiteralEnum.One, Decl(templateLiteralTypes4.ts, 42, 58))
>NumberLiteralEnum.One : Symbol(NumberLiteralEnum.One, Decl(templateLiteralTypes4.ts, 38, 36))
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>One : Symbol(NumberLiteralEnum.One, Decl(templateLiteralTypes4.ts, 38, 36))
type TNonLiteralEnum0 = "0" extends `${infer T extends NonLiteralEnum}` ? T : never; // 0
>TNonLiteralEnum0 : Symbol(TNonLiteralEnum0, Decl(templateLiteralTypes4.ts, 42, 88))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 43, 44))
>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 43, 44))
// infer using priority:
// string > template-literal > (string-literal | string-literal-enum) >
// number > enum > (number-literal | number-literal-enum) >
// bigint > bigint-literal >
// boolean > (boolean-literal | undefined | null)
// #region string
// string > string-literal-enum
type PString00 = "0" extends `${infer T extends string | StringLiteralEnum}` ? T : never; // "0"
>PString00 : Symbol(PString00, Decl(templateLiteralTypes4.ts, 43, 84))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 53, 37))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 53, 37))
// string > number
type PString01 = "0" extends `${infer T extends string | number}` ? T : never; // "0"
>PString01 : Symbol(PString01, Decl(templateLiteralTypes4.ts, 53, 89))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 37))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 56, 37))
// string > enum
type PString02 = "0" extends `${infer T extends string | NonLiteralEnum}` ? T : never; // "0"
>PString02 : Symbol(PString02, Decl(templateLiteralTypes4.ts, 56, 78))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 59, 37))
>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 59, 37))
// string > (number-literal | number-literal-enum)
type PString03 = "0" extends `${infer T extends string | 0}` ? T : never; // "0"
>PString03 : Symbol(PString03, Decl(templateLiteralTypes4.ts, 59, 86))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 62, 37))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 62, 37))
type PString04 = "0" extends `${infer T extends string | NumberLiteralEnum}` ? T : never; // "0"
>PString04 : Symbol(PString04, Decl(templateLiteralTypes4.ts, 62, 73))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 63, 37))
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 63, 37))
// string > bigint
type PString05 = "0" extends `${infer T extends string | bigint}` ? T : never; // "0"
>PString05 : Symbol(PString05, Decl(templateLiteralTypes4.ts, 63, 89))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 66, 37))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 66, 37))
// string > bigint-literal
type PString06 = "0" extends `${infer T extends string | 0n}` ? T : never; // "0"
>PString06 : Symbol(PString06, Decl(templateLiteralTypes4.ts, 66, 78))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 69, 37))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 69, 37))
// string > boolean
type PString07 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true"
>PString07 : Symbol(PString07, Decl(templateLiteralTypes4.ts, 69, 74))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 72, 40))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 72, 40))
type PString08 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false"
>PString08 : Symbol(PString08, Decl(templateLiteralTypes4.ts, 72, 82))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 73, 41))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 73, 41))
// string > (boolean-literal | undefined | null)
type PString09 = "true" extends `${infer T extends string | true}` ? T : never; // "true"
>PString09 : Symbol(PString09, Decl(templateLiteralTypes4.ts, 73, 83))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 40))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 76, 40))
type PString10 = "false" extends `${infer T extends string | false}` ? T : never; // "false"
>PString10 : Symbol(PString10, Decl(templateLiteralTypes4.ts, 76, 79))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 77, 41))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 77, 41))
type PString11 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined"
>PString11 : Symbol(PString11, Decl(templateLiteralTypes4.ts, 77, 81))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 78, 45))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 78, 45))
type PString12 = "null" extends `${infer T extends string | null}` ? T : never; // "null"
>PString12 : Symbol(PString12, Decl(templateLiteralTypes4.ts, 78, 89))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 79, 40))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 79, 40))
// #endregion string
// #region template-literal
// template-literal > number
type PTemplate00 = "10" extends `${infer T extends `1${string}` | number}` ? T : never; // "10"
>PTemplate00 : Symbol(PTemplate00, Decl(templateLiteralTypes4.ts, 79, 79))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 84, 40))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 84, 40))
// template-literal > enum
type PTemplate01 = "10" extends `${infer T extends `1${string}` | NonLiteralEnum}` ? T : never; // "10"
>PTemplate01 : Symbol(PTemplate01, Decl(templateLiteralTypes4.ts, 84, 87))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 87, 40))
>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 87, 40))
// template-literal > (number-literal | number-literal-enum)
type PTemplate02 = "10" extends `${infer T extends `1${string}` | 10}` ? T : never; // "10"
>PTemplate02 : Symbol(PTemplate02, Decl(templateLiteralTypes4.ts, 87, 95))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 90, 40))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 90, 40))
type PTemplate03 = "10" extends `${infer T extends `1${string}` | NumberLiteralEnum}` ? T : never; // "10"
>PTemplate03 : Symbol(PTemplate03, Decl(templateLiteralTypes4.ts, 90, 83))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 91, 40))
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 91, 40))
// template-literal > bigint
type PTemplate04 = "10" extends `${infer T extends `1${string}` | bigint}` ? T : never; // "10"
>PTemplate04 : Symbol(PTemplate04, Decl(templateLiteralTypes4.ts, 91, 98))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 94, 40))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 94, 40))
// template-literal > bigint-literal
type PTemplate05 = "10" extends `${infer T extends `1${string}` | 10n}` ? T : never; // "10"
>PTemplate05 : Symbol(PTemplate05, Decl(templateLiteralTypes4.ts, 94, 87))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 97, 40))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 97, 40))
// template-literal > boolean
type PTemplate06 = "true" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "true"
>PTemplate06 : Symbol(PTemplate06, Decl(templateLiteralTypes4.ts, 97, 84))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 100, 42))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 100, 42))
type PTemplate07 = "false" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "false"
>PTemplate07 : Symbol(PTemplate07, Decl(templateLiteralTypes4.ts, 100, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 101, 43))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 101, 43))
// template-literal > (boolean-literal | undefined | null)
type PTemplate08 = "true" extends `${infer T extends `${"t"}${string}` | true}` ? T : never; // "true"
>PTemplate08 : Symbol(PTemplate08, Decl(templateLiteralTypes4.ts, 101, 91))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 104, 42))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 104, 42))
type PTemplate09 = "false" extends `${infer T extends `${"f"}${string}` | false}` ? T : never; // "false"
>PTemplate09 : Symbol(PTemplate09, Decl(templateLiteralTypes4.ts, 104, 92))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 105, 43))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 105, 43))
type PTemplate10 = "undefined" extends `${infer T extends `${"u"}${string}` | undefined}` ? T : never; // "undefined"
>PTemplate10 : Symbol(PTemplate10, Decl(templateLiteralTypes4.ts, 105, 94))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 106, 47))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 106, 47))
type PTemplate11 = "null" extends `${infer T extends `${"n"}${string}` | null}` ? T : never; // "null"
>PTemplate11 : Symbol(PTemplate11, Decl(templateLiteralTypes4.ts, 106, 102))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 107, 42))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 107, 42))
// #endregion template-literal
// #region string-literal
// string-literal > number
type PStringLiteral00 = "0" extends `${infer T extends "0" | number}` ? T : never; // "0"
>PStringLiteral00 : Symbol(PStringLiteral00, Decl(templateLiteralTypes4.ts, 107, 92))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 112, 44))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 112, 44))
// string-literal > enum
type PStringLiteral01 = "0" extends `${infer T extends "0" | NonLiteralEnum}` ? T : never; // "0"
>PStringLiteral01 : Symbol(PStringLiteral01, Decl(templateLiteralTypes4.ts, 112, 82))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 115, 44))
>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 115, 44))
// string-literal > (number-literal | number-literal-enum)
type PStringLiteral02 = "0" extends `${infer T extends "0" | 0}` ? T : never; // "0"
>PStringLiteral02 : Symbol(PStringLiteral02, Decl(templateLiteralTypes4.ts, 115, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 118, 44))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 118, 44))
type PStringLiteral03 = "0" extends `${infer T extends "0" | NumberLiteralEnum}` ? T : never; // "0"
>PStringLiteral03 : Symbol(PStringLiteral03, Decl(templateLiteralTypes4.ts, 118, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 119, 44))
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 119, 44))
// string-literal > bigint
type PStringLiteral04 = "0" extends `${infer T extends "0" | bigint}` ? T : never; // "0"
>PStringLiteral04 : Symbol(PStringLiteral04, Decl(templateLiteralTypes4.ts, 119, 93))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 122, 44))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 122, 44))
// string-literal > bigint-literal
type PStringLiteral05 = "0" extends `${infer T extends "0" | 0n}` ? T : never; // "0"
>PStringLiteral05 : Symbol(PStringLiteral05, Decl(templateLiteralTypes4.ts, 122, 82))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 125, 44))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 125, 44))
// string-literal > boolean
type PStringLiteral06 = "true" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "true"
>PStringLiteral06 : Symbol(PStringLiteral06, Decl(templateLiteralTypes4.ts, 125, 78))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 128, 47))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 128, 47))
type PStringLiteral07 = "false" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "false"
>PStringLiteral07 : Symbol(PStringLiteral07, Decl(templateLiteralTypes4.ts, 128, 99))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 129, 48))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 129, 48))
// string-literal > (boolean-literal | undefined | null)
type PStringLiteral08 = "true" extends `${infer T extends "true" | true}` ? T : never; // "true"
>PStringLiteral08 : Symbol(PStringLiteral08, Decl(templateLiteralTypes4.ts, 129, 100))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 132, 47))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 132, 47))
type PStringLiteral09 = "false" extends `${infer T extends "false" | false}` ? T : never; // "false"
>PStringLiteral09 : Symbol(PStringLiteral09, Decl(templateLiteralTypes4.ts, 132, 86))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 133, 48))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 133, 48))
type PStringLiteral10 = "undefined" extends `${infer T extends "undefined" | undefined}` ? T : never; // "undefined"
>PStringLiteral10 : Symbol(PStringLiteral10, Decl(templateLiteralTypes4.ts, 133, 89))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 134, 52))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 134, 52))
type PStringLiteral11 = "null" extends `${infer T extends "null" | null}` ? T : never; // "null"
>PStringLiteral11 : Symbol(PStringLiteral11, Decl(templateLiteralTypes4.ts, 134, 101))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 135, 47))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 135, 47))
// #endregion string-literal
// #region string-literal-enum
// string-literal-enum > number
type PStringLiteralEnum00 = "0" extends `${infer T extends StringLiteralEnum | number}` ? T : never; // StringLiteralEnum.Zero
>PStringLiteralEnum00 : Symbol(PStringLiteralEnum00, Decl(templateLiteralTypes4.ts, 135, 86))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 140, 48))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 140, 48))
// string-literal-enum > enum
type PStringLiteralEnum01 = "0" extends `${infer T extends StringLiteralEnum | NonLiteralEnum}` ? T : never; // StringLiteralEnum.Zero
>PStringLiteralEnum01 : Symbol(PStringLiteralEnum01, Decl(templateLiteralTypes4.ts, 140, 100))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 143, 48))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 143, 48))
// string-literal-enum > (number-literal | number-literal-enum)
type PStringLiteralEnum02 = "0" extends `${infer T extends StringLiteralEnum | 0}` ? T : never; // StringLiteralEnum.Zero
>PStringLiteralEnum02 : Symbol(PStringLiteralEnum02, Decl(templateLiteralTypes4.ts, 143, 108))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 146, 48))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 146, 48))
type PStringLiteralEnum03 = "0" extends `${infer T extends StringLiteralEnum | NumberLiteralEnum}` ? T : never; // StringLiteralEnum.Zero
>PStringLiteralEnum03 : Symbol(PStringLiteralEnum03, Decl(templateLiteralTypes4.ts, 146, 95))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 147, 48))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 147, 48))
// string-literal-enum > bigint
type PStringLiteralEnum04 = "0" extends `${infer T extends StringLiteralEnum | bigint}` ? T : never; // StringLiteralEnum.Zero
>PStringLiteralEnum04 : Symbol(PStringLiteralEnum04, Decl(templateLiteralTypes4.ts, 147, 111))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 150, 48))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 150, 48))
// string-literal-enum > bigint-literal
type PStringLiteralEnum05 = "0" extends `${infer T extends StringLiteralEnum | 0n}` ? T : never; // StringLiteralEnum.Zero
>PStringLiteralEnum05 : Symbol(PStringLiteralEnum05, Decl(templateLiteralTypes4.ts, 150, 100))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 153, 48))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 153, 48))
// string-literal-enum > boolean
type PStringLiteralEnum06 = "true" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.True
>PStringLiteralEnum06 : Symbol(PStringLiteralEnum06, Decl(templateLiteralTypes4.ts, 153, 96))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 156, 51))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 156, 51))
type PStringLiteralEnum07 = "false" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.False
>PStringLiteralEnum07 : Symbol(PStringLiteralEnum07, Decl(templateLiteralTypes4.ts, 156, 104))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 157, 52))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 157, 52))
// string-literal-enum > (boolean-literal | undefined | null)
type PStringLiteralEnum08 = "true" extends `${infer T extends StringLiteralEnum | true}` ? T : never; // StringLiteralEnum.True
>PStringLiteralEnum08 : Symbol(PStringLiteralEnum08, Decl(templateLiteralTypes4.ts, 157, 105))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 160, 51))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 160, 51))
type PStringLiteralEnum09 = "false" extends `${infer T extends StringLiteralEnum | false}` ? T : never; // StringLiteralEnum.False
>PStringLiteralEnum09 : Symbol(PStringLiteralEnum09, Decl(templateLiteralTypes4.ts, 160, 101))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 161, 52))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 161, 52))
type PStringLiteralEnum10 = "undefined" extends `${infer T extends StringLiteralEnum | undefined}` ? T : never; // StringLiteralEnum.Undefined
>PStringLiteralEnum10 : Symbol(PStringLiteralEnum10, Decl(templateLiteralTypes4.ts, 161, 103))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 162, 56))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 162, 56))
type PStringLiteralEnum11 = "null" extends `${infer T extends StringLiteralEnum | null}` ? T : never; // StringLiteralEnum.Null
>PStringLiteralEnum11 : Symbol(PStringLiteralEnum11, Decl(templateLiteralTypes4.ts, 162, 111))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 163, 51))
>StringLiteralEnum : Symbol(StringLiteralEnum, Decl(templateLiteralTypes4.ts, 32, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 163, 51))
// #endregion string-literal-enum
// #region number
// number > enum
type PNumber0 = "0" extends `${infer T extends number | NonLiteralEnum}` ? T : never; // 0
>PNumber0 : Symbol(PNumber0, Decl(templateLiteralTypes4.ts, 163, 101))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 168, 36))
>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 168, 36))
// number > number-literal-enum
type PNumber1 = "0" extends `${infer T extends number | NumberLiteralEnum}` ? T : never; // 0
>PNumber1 : Symbol(PNumber1, Decl(templateLiteralTypes4.ts, 168, 85))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 171, 36))
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 171, 36))
// number > bigint
type PNumber2 = "0" extends `${infer T extends number | bigint}` ? T : never; // 0
>PNumber2 : Symbol(PNumber2, Decl(templateLiteralTypes4.ts, 171, 88))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 174, 36))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 174, 36))
// number > bigint-literal
type PNumber3 = "0" extends `${infer T extends number | 0n}` ? T : never; // 0
>PNumber3 : Symbol(PNumber3, Decl(templateLiteralTypes4.ts, 174, 77))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 177, 36))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 177, 36))
// #endregion number
// #region enum
// enum > number-literal-enum
type PEnum0 = "0" extends `${infer T extends NonLiteralEnum | NumberLiteralEnum}` ? T : never; // 0
>PEnum0 : Symbol(PEnum0, Decl(templateLiteralTypes4.ts, 177, 73))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 182, 34))
>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90))
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 182, 34))
// enum > bigint
type PEnum1 = "0" extends `${infer T extends NonLiteralEnum | bigint}` ? T : never; // 0
>PEnum1 : Symbol(PEnum1, Decl(templateLiteralTypes4.ts, 182, 94))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 185, 34))
>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 185, 34))
// enum > bigint-literal
type PEnum2 = "0" extends `${infer T extends NonLiteralEnum | 0n}` ? T : never; // 0
>PEnum2 : Symbol(PEnum2, Decl(templateLiteralTypes4.ts, 185, 83))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 188, 34))
>NonLiteralEnum : Symbol(NonLiteralEnum, Decl(templateLiteralTypes4.ts, 39, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 188, 34))
// #endregion enum
// #region number-literal
// number-literal > bigint
type PNumberLiteral0 = "0" extends `${infer T extends 0 | bigint}` ? T : never; // 0
>PNumberLiteral0 : Symbol(PNumberLiteral0, Decl(templateLiteralTypes4.ts, 188, 79))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 193, 43))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 193, 43))
// number-literal > bigint-literal
type PNumberLiteral1 = "0" extends `${infer T extends 0 | 0n}` ? T : never; // 0
>PNumberLiteral1 : Symbol(PNumberLiteral1, Decl(templateLiteralTypes4.ts, 193, 79))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 196, 43))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 196, 43))
// #endregion number-literal
// #region number-literal-enum
// number-literal-enum > bigint
type PNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum | bigint}` ? T : never; // NumberLiteralEnum.Zero
>PNumberLiteralEnum0 : Symbol(PNumberLiteralEnum0, Decl(templateLiteralTypes4.ts, 196, 75))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 201, 47))
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 201, 47))
// number-literal-enum > bigint-literal
type PNumberLiteralEnum1 = "0" extends `${infer T extends NumberLiteralEnum | 0n}` ? T : never; // NumberLiteralEnum.Zero
>PNumberLiteralEnum1 : Symbol(PNumberLiteralEnum1, Decl(templateLiteralTypes4.ts, 201, 99))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 204, 47))
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 204, 47))
// #endregion number-literal-enum
// non-matchable constituents are excluded
type PExclude0 = "0" extends `${infer T extends "1" | number}` ? T : never; // 0
>PExclude0 : Symbol(PExclude0, Decl(templateLiteralTypes4.ts, 204, 95))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 208, 37))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 208, 37))
type PExclude1 = "0" extends `${infer T extends `1${string}` | number}` ? T : never; // 0
>PExclude1 : Symbol(PExclude1, Decl(templateLiteralTypes4.ts, 208, 75))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 209, 37))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 209, 37))
type PExclude2 = "0" extends `${infer T extends 1 | bigint}` ? T : never; // 0n
>PExclude2 : Symbol(PExclude2, Decl(templateLiteralTypes4.ts, 209, 84))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 210, 37))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 210, 37))
type PExclude3 = "0" extends `${infer T extends NumberLiteralEnum.One | bigint}` ? T : never; // 0n
>PExclude3 : Symbol(PExclude3, Decl(templateLiteralTypes4.ts, 210, 73))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 211, 37))
>NumberLiteralEnum : Symbol(NumberLiteralEnum, Decl(templateLiteralTypes4.ts, 36, 90))
>One : Symbol(NumberLiteralEnum.One, Decl(templateLiteralTypes4.ts, 38, 36))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 211, 37))
type PExclude4 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n
>PExclude4 : Symbol(PExclude4, Decl(templateLiteralTypes4.ts, 211, 93))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 212, 60))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 212, 60))
// infer to prefix from string
type TPrefix0 = "100" extends `${infer T extends number}${string}` ? T : never; // 1
>TPrefix0 : Symbol(TPrefix0, Decl(templateLiteralTypes4.ts, 212, 101))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 215, 38))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 215, 38))
type TPrefix1 = "trueabc" extends `${infer T extends boolean}${string}` ? T : never; // boolean (T only receives 't', not the whole string)
>TPrefix1 : Symbol(TPrefix1, Decl(templateLiteralTypes4.ts, 215, 79))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 216, 42))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 216, 42))
type TPrefix2 = `100:${string}` extends `${infer T extends number}:${string}` ? T : never; // 100 (T receives '100' because it scans until ':')
>TPrefix2 : Symbol(TPrefix2, Decl(templateLiteralTypes4.ts, 216, 84))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 217, 48))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 217, 48))
// can use union w/multiple branches to extract each possibility
type ExtractPrimitives<T extends string> =
>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 217, 90))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 220, 23))
| T
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 220, 23))
| (T extends `${infer U extends number}` ? U : never)
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 220, 23))
>U : Symbol(U, Decl(templateLiteralTypes4.ts, 222, 25))
>U : Symbol(U, Decl(templateLiteralTypes4.ts, 222, 25))
| (T extends `${infer U extends bigint}` ? U : never)
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 220, 23))
>U : Symbol(U, Decl(templateLiteralTypes4.ts, 223, 25))
>U : Symbol(U, Decl(templateLiteralTypes4.ts, 223, 25))
| (T extends `${infer U extends boolean | null | undefined}` ? U : never)
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 220, 23))
>U : Symbol(U, Decl(templateLiteralTypes4.ts, 224, 25))
>U : Symbol(U, Decl(templateLiteralTypes4.ts, 224, 25))
;
type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n
>TExtract0 : Symbol(TExtract0, Decl(templateLiteralTypes4.ts, 225, 5))
>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 217, 90))
type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1
>TExtract1 : Symbol(TExtract1, Decl(templateLiteralTypes4.ts, 227, 42))
>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 217, 90))
type TExtract2 = ExtractPrimitives<"true">; // "true" | true
>TExtract2 : Symbol(TExtract2, Decl(templateLiteralTypes4.ts, 228, 42))
>ExtractPrimitives : Symbol(ExtractPrimitives, Decl(templateLiteralTypes4.ts, 217, 90))
// example use case (based on old TypedObjects proposal):
// Use constrained `infer` in template literal to get ordinal indices as numbers:
type IndexFor<S extends string> = S extends `${infer N extends number}` ? N : never;
>IndexFor : Symbol(IndexFor, Decl(templateLiteralTypes4.ts, 229, 43))
>S : Symbol(S, Decl(templateLiteralTypes4.ts, 236, 14))
>S : Symbol(S, Decl(templateLiteralTypes4.ts, 236, 14))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 236, 52))
>N : Symbol(N, Decl(templateLiteralTypes4.ts, 236, 52))
type IndicesOf<T> = IndexFor<Extract<keyof T, string>>; // ordinal indices as number literals
>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 236, 84))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 237, 15))
>IndexFor : Symbol(IndexFor, Decl(templateLiteralTypes4.ts, 229, 43))
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 237, 15))
interface FieldDefinition {
>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55))
readonly name: string;
>name : Symbol(FieldDefinition.name, Decl(templateLiteralTypes4.ts, 239, 27))
readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64";
>type : Symbol(FieldDefinition.type, Decl(templateLiteralTypes4.ts, 240, 26))
}
type FieldType<T extends FieldDefinition["type"]> =
>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 244, 15))
>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55))
T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number :
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 244, 15))
T extends "f32" | "f64" ? bigint :
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 244, 15))
never;
// Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]`
type TypedObjectNamedMembers<TDef extends readonly FieldDefinition[]> = {
>TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 247, 10))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 250, 29))
>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55))
[P in TDef[number]["name"]]: FieldType<Extract<TDef[number], { readonly name: P }>["type"]>;
>P : Symbol(P, Decl(templateLiteralTypes4.ts, 251, 5))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 250, 29))
>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1))
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 250, 29))
>name : Symbol(name, Decl(templateLiteralTypes4.ts, 251, 66))
>P : Symbol(P, Decl(templateLiteralTypes4.ts, 251, 5))
};
// Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]`
type TypedObjectOrdinalMembers<TDef extends readonly FieldDefinition[]> = {
>TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 252, 2))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 255, 31))
>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55))
[I in Extract<keyof TDef, `${number}`>]: FieldType<Extract<TDef[I], FieldDefinition>["type"]>;
>I : Symbol(I, Decl(templateLiteralTypes4.ts, 256, 5))
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 255, 31))
>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1))
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 255, 31))
>I : Symbol(I, Decl(templateLiteralTypes4.ts, 256, 5))
>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55))
};
// Default members
interface TypedObjectMembers<TDef extends readonly FieldDefinition[]> {
>TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 257, 2))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29))
>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55))
// get/set a field by name
get<K extends TDef[number]["name"]>(key: K): FieldType<Extract<TDef[number], { readonly name: K }>["type"]>;
>get : Symbol(TypedObjectMembers.get, Decl(templateLiteralTypes4.ts, 260, 71))
>K : Symbol(K, Decl(templateLiteralTypes4.ts, 262, 8))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29))
>key : Symbol(key, Decl(templateLiteralTypes4.ts, 262, 40))
>K : Symbol(K, Decl(templateLiteralTypes4.ts, 262, 8))
>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1))
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29))
>name : Symbol(name, Decl(templateLiteralTypes4.ts, 262, 82))
>K : Symbol(K, Decl(templateLiteralTypes4.ts, 262, 8))
set<K extends TDef[number]["name"]>(key: K, value: FieldType<Extract<TDef[number], { readonly name: K }>["type"]>): void;
>set : Symbol(TypedObjectMembers.set, Decl(templateLiteralTypes4.ts, 262, 112))
>K : Symbol(K, Decl(templateLiteralTypes4.ts, 263, 8))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29))
>key : Symbol(key, Decl(templateLiteralTypes4.ts, 263, 40))
>K : Symbol(K, Decl(templateLiteralTypes4.ts, 263, 8))
>value : Symbol(value, Decl(templateLiteralTypes4.ts, 263, 47))
>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1))
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29))
>name : Symbol(name, Decl(templateLiteralTypes4.ts, 263, 88))
>K : Symbol(K, Decl(templateLiteralTypes4.ts, 263, 8))
// get/set a field by index
getIndex<I extends IndicesOf<TDef>>(index: I): FieldType<Extract<TDef[I], FieldDefinition>["type"]>;
>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125))
>I : Symbol(I, Decl(templateLiteralTypes4.ts, 266, 13))
>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 236, 84))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29))
>index : Symbol(index, Decl(templateLiteralTypes4.ts, 266, 40))
>I : Symbol(I, Decl(templateLiteralTypes4.ts, 266, 13))
>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1))
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29))
>I : Symbol(I, Decl(templateLiteralTypes4.ts, 266, 13))
>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55))
setIndex<I extends IndicesOf<TDef>>(index: I, value: FieldType<Extract<TDef[I], FieldDefinition>["type"]>): void;
>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104))
>I : Symbol(I, Decl(templateLiteralTypes4.ts, 267, 13))
>IndicesOf : Symbol(IndicesOf, Decl(templateLiteralTypes4.ts, 236, 84))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29))
>index : Symbol(index, Decl(templateLiteralTypes4.ts, 267, 40))
>I : Symbol(I, Decl(templateLiteralTypes4.ts, 267, 13))
>value : Symbol(value, Decl(templateLiteralTypes4.ts, 267, 49))
>FieldType : Symbol(FieldType, Decl(templateLiteralTypes4.ts, 242, 1))
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 260, 29))
>I : Symbol(I, Decl(templateLiteralTypes4.ts, 267, 13))
>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55))
}
type TypedObject<TDef extends readonly FieldDefinition[]> =
>TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 268, 1))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 270, 17))
>FieldDefinition : Symbol(FieldDefinition, Decl(templateLiteralTypes4.ts, 237, 55))
& TypedObjectMembers<TDef>
>TypedObjectMembers : Symbol(TypedObjectMembers, Decl(templateLiteralTypes4.ts, 257, 2))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 270, 17))
& TypedObjectNamedMembers<TDef>
>TypedObjectNamedMembers : Symbol(TypedObjectNamedMembers, Decl(templateLiteralTypes4.ts, 247, 10))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 270, 17))
& TypedObjectOrdinalMembers<TDef>;
>TypedObjectOrdinalMembers : Symbol(TypedObjectOrdinalMembers, Decl(templateLiteralTypes4.ts, 252, 2))
>TDef : Symbol(TDef, Decl(templateLiteralTypes4.ts, 270, 17))
// NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type
type Point = TypedObject<[
>Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 273, 38))
>TypedObject : Symbol(TypedObject, Decl(templateLiteralTypes4.ts, 268, 1))
{ name: "x", type: "f64" },
>name : Symbol(name, Decl(templateLiteralTypes4.ts, 277, 5))
>type : Symbol(type, Decl(templateLiteralTypes4.ts, 277, 16))
{ name: "y", type: "f64" },
>name : Symbol(name, Decl(templateLiteralTypes4.ts, 278, 5))
>type : Symbol(type, Decl(templateLiteralTypes4.ts, 278, 16))
]>;
declare const p: Point;
>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13))
>Point : Symbol(Point, Decl(templateLiteralTypes4.ts, 273, 38))
p.getIndex(0); // ok, 0 is a valid index
>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125))
>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13))
>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125))
p.getIndex(1); // ok, 1 is a valid index
>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125))
>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13))
>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125))
p.getIndex(2); // error, 2 is not a valid index
>p.getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125))
>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13))
>getIndex : Symbol(TypedObjectMembers.getIndex, Decl(templateLiteralTypes4.ts, 263, 125))
p.setIndex(0, 0); // ok, 0 is a valid index
>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104))
>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13))
>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104))
p.setIndex(1, 0); // ok, 1 is a valid index
>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104))
>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13))
>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104))
p.setIndex(2, 3); // error, 2 is not a valid index
>p.setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104))
>p : Symbol(p, Decl(templateLiteralTypes4.ts, 281, 13))
>setIndex : Symbol(TypedObjectMembers.setIndex, Decl(templateLiteralTypes4.ts, 266, 104))
// function inference
declare function f1<T extends string | number>(s: `**${T}**`): T;
>f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 288, 17))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 291, 20))
>s : Symbol(s, Decl(templateLiteralTypes4.ts, 291, 47))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 291, 20))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 291, 20))
f1("**123**"); // "123"
>f1 : Symbol(f1, Decl(templateLiteralTypes4.ts, 288, 17))
declare function f2<T extends number>(s: `**${T}**`): T;
>f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 292, 14))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 294, 20))
>s : Symbol(s, Decl(templateLiteralTypes4.ts, 294, 38))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 294, 20))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 294, 20))
f2("**123**"); // 123
>f2 : Symbol(f2, Decl(templateLiteralTypes4.ts, 292, 14))
declare function f3<T extends bigint>(s: `**${T}**`): T;
>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 295, 14))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 297, 20))
>s : Symbol(s, Decl(templateLiteralTypes4.ts, 297, 38))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 297, 20))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 297, 20))
f3("**123**"); // 123n
>f3 : Symbol(f3, Decl(templateLiteralTypes4.ts, 295, 14))
declare function f4<T extends boolean>(s: `**${T}**`): T;
>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 298, 14))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 300, 20))
>s : Symbol(s, Decl(templateLiteralTypes4.ts, 300, 39))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 300, 20))
>T : Symbol(T, Decl(templateLiteralTypes4.ts, 300, 20))
f4("**true**"); // true | "true"
>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 298, 14))
f4("**false**"); // false | "false"
>f4 : Symbol(f4, Decl(templateLiteralTypes4.ts, 298, 14))
@@ -0,0 +1,608 @@
=== tests/cases/conformance/types/literal/templateLiteralTypes4.ts ===
// infer from number
type TNumber0 = "100" extends `${infer N extends number}` ? N : never; // 100
>TNumber0 : 100
type TNumber1 = "-100" extends `${infer N extends number}` ? N : never; // -100
>TNumber1 : -100
type TNumber2 = "1.1" extends `${infer N extends number}` ? N : never; // 1.1
>TNumber2 : 1.1
type TNumber3 = "8e-11" extends `${infer N extends number}` ? N : never; // 8e-11 (0.00000000008)
>TNumber3 : 8e-11
type TNumber4 = "0x10" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
>TNumber4 : number
type TNumber5 = "0o10" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
>TNumber5 : number
type TNumber6 = "0b10" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
>TNumber6 : number
type TNumber7 = "10e2" extends `${infer N extends number}` ? N : never; // number (not round-trippable)
>TNumber7 : number
type TNumber8 = "abcd" extends `${infer N extends number}` ? N : never; // never
>TNumber8 : never
// infer from bigint
type TBigInt0 = "100" extends `${infer N extends bigint}` ? N : never; // 100n
>TBigInt0 : 100n
type TBigInt1 = "-100" extends `${infer N extends bigint}` ? N : never; // -100n
>TBigInt1 : -100n
type TBigInt2 = "0x10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable)
>TBigInt2 : bigint
type TBigInt3 = "0o10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable)
>TBigInt3 : bigint
type TBigInt4 = "0b10" extends `${infer N extends bigint}` ? N : never; // bigint (not round-trippable)
>TBigInt4 : bigint
type TBigInt5 = "1.1" extends `${infer N extends bigint}` ? N : never; // never
>TBigInt5 : never
type TBigInt6 = "10e2" extends `${infer N extends bigint}` ? N : never; // never
>TBigInt6 : never
type TBigInt7 = "abcd" extends `${infer N extends bigint}` ? N : never; // never
>TBigInt7 : never
// infer from boolean
type TBoolean0 = "true" extends `${infer T extends boolean}` ? T : never; // true
>TBoolean0 : true
type TBoolean1 = "false" extends `${infer T extends boolean}` ? T : never; // false
>TBoolean1 : false
type TBoolean2 = "abcd" extends `${infer T extends boolean}` ? T : never; // never
>TBoolean2 : never
// infer from null
type TNull0 = "null" extends `${infer T extends null}` ? T : never; // null
>TNull0 : null
>null : null
type TNull1 = "abcd" extends `${infer T extends null}` ? T : never; // never
>TNull1 : never
>null : null
// infer from undefined
type TUndefined0 = "undefined" extends `${infer T extends undefined}` ? T : never; // undefined
>TUndefined0 : undefined
type TUndefined1 = "abcd" extends `${infer T extends undefined}` ? T : never; // never
>TUndefined1 : never
// infer from literal enums
const enum StringLiteralEnum { Zero = "0", True = "true", False = "false", Undefined = "undefined", Null = "null" }
>StringLiteralEnum : StringLiteralEnum
>Zero : StringLiteralEnum.Zero
>"0" : "0"
>True : StringLiteralEnum.True
>"true" : "true"
>False : StringLiteralEnum.False
>"false" : "false"
>Undefined : StringLiteralEnum.Undefined
>"undefined" : "undefined"
>Null : StringLiteralEnum.Null
>"null" : "null"
type TStringLiteralEnum0 = "0" extends `${infer T extends StringLiteralEnum}` ? T : never; // StringLiteralEnum.Zero
>TStringLiteralEnum0 : StringLiteralEnum.Zero
const enum NumberLiteralEnum { Zero, One }
>NumberLiteralEnum : NumberLiteralEnum
>Zero : NumberLiteralEnum.Zero
>One : NumberLiteralEnum.One
type TNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum}` ? T : never; // NumberLiteralEnum.Zero
>TNumberLiteralEnum0 : NumberLiteralEnum.Zero
// infer from non-literal enums
const enum NonLiteralEnum { Zero = NumberLiteralEnum.Zero, One = NumberLiteralEnum.One }
>NonLiteralEnum : NonLiteralEnum
>Zero : NonLiteralEnum
>NumberLiteralEnum.Zero : NumberLiteralEnum.Zero
>NumberLiteralEnum : typeof NumberLiteralEnum
>Zero : NumberLiteralEnum.Zero
>One : NonLiteralEnum
>NumberLiteralEnum.One : NumberLiteralEnum.One
>NumberLiteralEnum : typeof NumberLiteralEnum
>One : NumberLiteralEnum.One
type TNonLiteralEnum0 = "0" extends `${infer T extends NonLiteralEnum}` ? T : never; // 0
>TNonLiteralEnum0 : 0
// infer using priority:
// string > template-literal > (string-literal | string-literal-enum) >
// number > enum > (number-literal | number-literal-enum) >
// bigint > bigint-literal >
// boolean > (boolean-literal | undefined | null)
// #region string
// string > string-literal-enum
type PString00 = "0" extends `${infer T extends string | StringLiteralEnum}` ? T : never; // "0"
>PString00 : "0"
// string > number
type PString01 = "0" extends `${infer T extends string | number}` ? T : never; // "0"
>PString01 : "0"
// string > enum
type PString02 = "0" extends `${infer T extends string | NonLiteralEnum}` ? T : never; // "0"
>PString02 : "0"
// string > (number-literal | number-literal-enum)
type PString03 = "0" extends `${infer T extends string | 0}` ? T : never; // "0"
>PString03 : "0"
type PString04 = "0" extends `${infer T extends string | NumberLiteralEnum}` ? T : never; // "0"
>PString04 : "0"
// string > bigint
type PString05 = "0" extends `${infer T extends string | bigint}` ? T : never; // "0"
>PString05 : "0"
// string > bigint-literal
type PString06 = "0" extends `${infer T extends string | 0n}` ? T : never; // "0"
>PString06 : "0"
// string > boolean
type PString07 = "true" extends `${infer T extends string | boolean}` ? T : never; // "true"
>PString07 : "true"
type PString08 = "false" extends `${infer T extends string | boolean}` ? T : never; // "false"
>PString08 : "false"
// string > (boolean-literal | undefined | null)
type PString09 = "true" extends `${infer T extends string | true}` ? T : never; // "true"
>PString09 : "true"
>true : true
type PString10 = "false" extends `${infer T extends string | false}` ? T : never; // "false"
>PString10 : "false"
>false : false
type PString11 = "undefined" extends `${infer T extends string | undefined}` ? T : never; // "undefined"
>PString11 : "undefined"
type PString12 = "null" extends `${infer T extends string | null}` ? T : never; // "null"
>PString12 : "null"
>null : null
// #endregion string
// #region template-literal
// template-literal > number
type PTemplate00 = "10" extends `${infer T extends `1${string}` | number}` ? T : never; // "10"
>PTemplate00 : "10"
// template-literal > enum
type PTemplate01 = "10" extends `${infer T extends `1${string}` | NonLiteralEnum}` ? T : never; // "10"
>PTemplate01 : "10"
// template-literal > (number-literal | number-literal-enum)
type PTemplate02 = "10" extends `${infer T extends `1${string}` | 10}` ? T : never; // "10"
>PTemplate02 : "10"
type PTemplate03 = "10" extends `${infer T extends `1${string}` | NumberLiteralEnum}` ? T : never; // "10"
>PTemplate03 : "10"
// template-literal > bigint
type PTemplate04 = "10" extends `${infer T extends `1${string}` | bigint}` ? T : never; // "10"
>PTemplate04 : "10"
// template-literal > bigint-literal
type PTemplate05 = "10" extends `${infer T extends `1${string}` | 10n}` ? T : never; // "10"
>PTemplate05 : "10"
// template-literal > boolean
type PTemplate06 = "true" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "true"
>PTemplate06 : "true"
type PTemplate07 = "false" extends `${infer T extends `${string}e` | boolean}` ? T : never; // "false"
>PTemplate07 : "false"
// template-literal > (boolean-literal | undefined | null)
type PTemplate08 = "true" extends `${infer T extends `${"t"}${string}` | true}` ? T : never; // "true"
>PTemplate08 : "true"
>true : true
type PTemplate09 = "false" extends `${infer T extends `${"f"}${string}` | false}` ? T : never; // "false"
>PTemplate09 : "false"
>false : false
type PTemplate10 = "undefined" extends `${infer T extends `${"u"}${string}` | undefined}` ? T : never; // "undefined"
>PTemplate10 : "undefined"
type PTemplate11 = "null" extends `${infer T extends `${"n"}${string}` | null}` ? T : never; // "null"
>PTemplate11 : "null"
>null : null
// #endregion template-literal
// #region string-literal
// string-literal > number
type PStringLiteral00 = "0" extends `${infer T extends "0" | number}` ? T : never; // "0"
>PStringLiteral00 : "0"
// string-literal > enum
type PStringLiteral01 = "0" extends `${infer T extends "0" | NonLiteralEnum}` ? T : never; // "0"
>PStringLiteral01 : "0"
// string-literal > (number-literal | number-literal-enum)
type PStringLiteral02 = "0" extends `${infer T extends "0" | 0}` ? T : never; // "0"
>PStringLiteral02 : "0"
type PStringLiteral03 = "0" extends `${infer T extends "0" | NumberLiteralEnum}` ? T : never; // "0"
>PStringLiteral03 : "0"
// string-literal > bigint
type PStringLiteral04 = "0" extends `${infer T extends "0" | bigint}` ? T : never; // "0"
>PStringLiteral04 : "0"
// string-literal > bigint-literal
type PStringLiteral05 = "0" extends `${infer T extends "0" | 0n}` ? T : never; // "0"
>PStringLiteral05 : "0"
// string-literal > boolean
type PStringLiteral06 = "true" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "true"
>PStringLiteral06 : "true"
type PStringLiteral07 = "false" extends `${infer T extends "true" | "false" | boolean}` ? T : never; // "false"
>PStringLiteral07 : "false"
// string-literal > (boolean-literal | undefined | null)
type PStringLiteral08 = "true" extends `${infer T extends "true" | true}` ? T : never; // "true"
>PStringLiteral08 : "true"
>true : true
type PStringLiteral09 = "false" extends `${infer T extends "false" | false}` ? T : never; // "false"
>PStringLiteral09 : "false"
>false : false
type PStringLiteral10 = "undefined" extends `${infer T extends "undefined" | undefined}` ? T : never; // "undefined"
>PStringLiteral10 : "undefined"
type PStringLiteral11 = "null" extends `${infer T extends "null" | null}` ? T : never; // "null"
>PStringLiteral11 : "null"
>null : null
// #endregion string-literal
// #region string-literal-enum
// string-literal-enum > number
type PStringLiteralEnum00 = "0" extends `${infer T extends StringLiteralEnum | number}` ? T : never; // StringLiteralEnum.Zero
>PStringLiteralEnum00 : StringLiteralEnum.Zero
// string-literal-enum > enum
type PStringLiteralEnum01 = "0" extends `${infer T extends StringLiteralEnum | NonLiteralEnum}` ? T : never; // StringLiteralEnum.Zero
>PStringLiteralEnum01 : StringLiteralEnum.Zero
// string-literal-enum > (number-literal | number-literal-enum)
type PStringLiteralEnum02 = "0" extends `${infer T extends StringLiteralEnum | 0}` ? T : never; // StringLiteralEnum.Zero
>PStringLiteralEnum02 : StringLiteralEnum.Zero
type PStringLiteralEnum03 = "0" extends `${infer T extends StringLiteralEnum | NumberLiteralEnum}` ? T : never; // StringLiteralEnum.Zero
>PStringLiteralEnum03 : StringLiteralEnum.Zero
// string-literal-enum > bigint
type PStringLiteralEnum04 = "0" extends `${infer T extends StringLiteralEnum | bigint}` ? T : never; // StringLiteralEnum.Zero
>PStringLiteralEnum04 : StringLiteralEnum.Zero
// string-literal-enum > bigint-literal
type PStringLiteralEnum05 = "0" extends `${infer T extends StringLiteralEnum | 0n}` ? T : never; // StringLiteralEnum.Zero
>PStringLiteralEnum05 : StringLiteralEnum.Zero
// string-literal-enum > boolean
type PStringLiteralEnum06 = "true" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.True
>PStringLiteralEnum06 : StringLiteralEnum.True
type PStringLiteralEnum07 = "false" extends `${infer T extends StringLiteralEnum | boolean}` ? T : never; // StringLiteralEnum.False
>PStringLiteralEnum07 : StringLiteralEnum.False
// string-literal-enum > (boolean-literal | undefined | null)
type PStringLiteralEnum08 = "true" extends `${infer T extends StringLiteralEnum | true}` ? T : never; // StringLiteralEnum.True
>PStringLiteralEnum08 : StringLiteralEnum.True
>true : true
type PStringLiteralEnum09 = "false" extends `${infer T extends StringLiteralEnum | false}` ? T : never; // StringLiteralEnum.False
>PStringLiteralEnum09 : StringLiteralEnum.False
>false : false
type PStringLiteralEnum10 = "undefined" extends `${infer T extends StringLiteralEnum | undefined}` ? T : never; // StringLiteralEnum.Undefined
>PStringLiteralEnum10 : StringLiteralEnum.Undefined
type PStringLiteralEnum11 = "null" extends `${infer T extends StringLiteralEnum | null}` ? T : never; // StringLiteralEnum.Null
>PStringLiteralEnum11 : StringLiteralEnum.Null
>null : null
// #endregion string-literal-enum
// #region number
// number > enum
type PNumber0 = "0" extends `${infer T extends number | NonLiteralEnum}` ? T : never; // 0
>PNumber0 : 0
// number > number-literal-enum
type PNumber1 = "0" extends `${infer T extends number | NumberLiteralEnum}` ? T : never; // 0
>PNumber1 : 0
// number > bigint
type PNumber2 = "0" extends `${infer T extends number | bigint}` ? T : never; // 0
>PNumber2 : 0
// number > bigint-literal
type PNumber3 = "0" extends `${infer T extends number | 0n}` ? T : never; // 0
>PNumber3 : 0
// #endregion number
// #region enum
// enum > number-literal-enum
type PEnum0 = "0" extends `${infer T extends NonLiteralEnum | NumberLiteralEnum}` ? T : never; // 0
>PEnum0 : 0
// enum > bigint
type PEnum1 = "0" extends `${infer T extends NonLiteralEnum | bigint}` ? T : never; // 0
>PEnum1 : 0
// enum > bigint-literal
type PEnum2 = "0" extends `${infer T extends NonLiteralEnum | 0n}` ? T : never; // 0
>PEnum2 : 0
// #endregion enum
// #region number-literal
// number-literal > bigint
type PNumberLiteral0 = "0" extends `${infer T extends 0 | bigint}` ? T : never; // 0
>PNumberLiteral0 : 0
// number-literal > bigint-literal
type PNumberLiteral1 = "0" extends `${infer T extends 0 | 0n}` ? T : never; // 0
>PNumberLiteral1 : 0
// #endregion number-literal
// #region number-literal-enum
// number-literal-enum > bigint
type PNumberLiteralEnum0 = "0" extends `${infer T extends NumberLiteralEnum | bigint}` ? T : never; // NumberLiteralEnum.Zero
>PNumberLiteralEnum0 : NumberLiteralEnum.Zero
// number-literal-enum > bigint-literal
type PNumberLiteralEnum1 = "0" extends `${infer T extends NumberLiteralEnum | 0n}` ? T : never; // NumberLiteralEnum.Zero
>PNumberLiteralEnum1 : NumberLiteralEnum.Zero
// #endregion number-literal-enum
// non-matchable constituents are excluded
type PExclude0 = "0" extends `${infer T extends "1" | number}` ? T : never; // 0
>PExclude0 : 0
type PExclude1 = "0" extends `${infer T extends `1${string}` | number}` ? T : never; // 0
>PExclude1 : 0
type PExclude2 = "0" extends `${infer T extends 1 | bigint}` ? T : never; // 0n
>PExclude2 : 0n
type PExclude3 = "0" extends `${infer T extends NumberLiteralEnum.One | bigint}` ? T : never; // 0n
>PExclude3 : 0n
>NumberLiteralEnum : any
type PExclude4 = "100000000000000000000000" extends `${infer T extends number | bigint}` ? T : never; // 100000000000000000000000n
>PExclude4 : 100000000000000000000000n
// infer to prefix from string
type TPrefix0 = "100" extends `${infer T extends number}${string}` ? T : never; // 1
>TPrefix0 : 1
type TPrefix1 = "trueabc" extends `${infer T extends boolean}${string}` ? T : never; // boolean (T only receives 't', not the whole string)
>TPrefix1 : boolean
type TPrefix2 = `100:${string}` extends `${infer T extends number}:${string}` ? T : never; // 100 (T receives '100' because it scans until ':')
>TPrefix2 : 100
// can use union w/multiple branches to extract each possibility
type ExtractPrimitives<T extends string> =
>ExtractPrimitives : ExtractPrimitives<T>
| T
| (T extends `${infer U extends number}` ? U : never)
| (T extends `${infer U extends bigint}` ? U : never)
| (T extends `${infer U extends boolean | null | undefined}` ? U : never)
>null : null
;
type TExtract0 = ExtractPrimitives<"100">; // "100" | 100 | 100n
>TExtract0 : "100" | 100 | 100n
type TExtract1 = ExtractPrimitives<"1.1">; // "1.1" | 1.1
>TExtract1 : "1.1" | 1.1
type TExtract2 = ExtractPrimitives<"true">; // "true" | true
>TExtract2 : true | "true"
// example use case (based on old TypedObjects proposal):
// Use constrained `infer` in template literal to get ordinal indices as numbers:
type IndexFor<S extends string> = S extends `${infer N extends number}` ? N : never;
>IndexFor : IndexFor<S>
type IndicesOf<T> = IndexFor<Extract<keyof T, string>>; // ordinal indices as number literals
>IndicesOf : IndicesOf<T>
interface FieldDefinition {
readonly name: string;
>name : string
readonly type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64";
>type : "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64"
}
type FieldType<T extends FieldDefinition["type"]> =
>FieldType : FieldType<T>
T extends "i8" | "i16" | "i32" | "u8" | "u16" | "u32" | "f32" | "f64" ? number :
T extends "f32" | "f64" ? bigint :
never;
// Generates named members like `{ x: number, y: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]`
type TypedObjectNamedMembers<TDef extends readonly FieldDefinition[]> = {
>TypedObjectNamedMembers : TypedObjectNamedMembers<TDef>
[P in TDef[number]["name"]]: FieldType<Extract<TDef[number], { readonly name: P }>["type"]>;
>name : P
};
// Generates ordinal members like `{ 0: number, 1: bigint }` from `[{ name: "x", type: "i32" }, { name: "y", type: "i64" }]`
type TypedObjectOrdinalMembers<TDef extends readonly FieldDefinition[]> = {
>TypedObjectOrdinalMembers : TypedObjectOrdinalMembers<TDef>
[I in Extract<keyof TDef, `${number}`>]: FieldType<Extract<TDef[I], FieldDefinition>["type"]>;
};
// Default members
interface TypedObjectMembers<TDef extends readonly FieldDefinition[]> {
// get/set a field by name
get<K extends TDef[number]["name"]>(key: K): FieldType<Extract<TDef[number], { readonly name: K }>["type"]>;
>get : <K extends TDef[number]["name"]>(key: K) => FieldType<Extract<TDef[number], { readonly name: K;}>["type"]>
>key : K
>name : K
set<K extends TDef[number]["name"]>(key: K, value: FieldType<Extract<TDef[number], { readonly name: K }>["type"]>): void;
>set : <K extends TDef[number]["name"]>(key: K, value: FieldType<Extract<TDef[number], { readonly name: K;}>["type"]>) => void
>key : K
>value : FieldType<Extract<TDef[number], { readonly name: K; }>["type"]>
>name : K
// get/set a field by index
getIndex<I extends IndicesOf<TDef>>(index: I): FieldType<Extract<TDef[I], FieldDefinition>["type"]>;
>getIndex : <I extends IndexFor<Extract<keyof TDef, string>>>(index: I) => FieldType<Extract<TDef[I], FieldDefinition>["type"]>
>index : I
setIndex<I extends IndicesOf<TDef>>(index: I, value: FieldType<Extract<TDef[I], FieldDefinition>["type"]>): void;
>setIndex : <I extends IndexFor<Extract<keyof TDef, string>>>(index: I, value: FieldType<Extract<TDef[I], FieldDefinition>["type"]>) => void
>index : I
>value : FieldType<Extract<TDef[I], FieldDefinition>["type"]>
}
type TypedObject<TDef extends readonly FieldDefinition[]> =
>TypedObject : TypedObject<TDef>
& TypedObjectMembers<TDef>
& TypedObjectNamedMembers<TDef>
& TypedObjectOrdinalMembers<TDef>;
// NOTE: type would normally be created from something like `const Point = TypedObject([...])` from which we would infer the type
type Point = TypedObject<[
>Point : TypedObjectMembers<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }]> & TypedObjectNamedMembers<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }]> & TypedObjectOrdinalMembers<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }]>
{ name: "x", type: "f64" },
>name : "x"
>type : "f64"
{ name: "y", type: "f64" },
>name : "y"
>type : "f64"
]>;
declare const p: Point;
>p : Point
p.getIndex(0); // ok, 0 is a valid index
>p.getIndex(0) : number
>p.getIndex : <I extends 0 | 1>(index: I) => FieldType<Extract<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }][I], FieldDefinition>["type"]>
>p : Point
>getIndex : <I extends 0 | 1>(index: I) => FieldType<Extract<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }][I], FieldDefinition>["type"]>
>0 : 0
p.getIndex(1); // ok, 1 is a valid index
>p.getIndex(1) : number
>p.getIndex : <I extends 0 | 1>(index: I) => FieldType<Extract<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }][I], FieldDefinition>["type"]>
>p : Point
>getIndex : <I extends 0 | 1>(index: I) => FieldType<Extract<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }][I], FieldDefinition>["type"]>
>1 : 1
p.getIndex(2); // error, 2 is not a valid index
>p.getIndex(2) : number
>p.getIndex : <I extends 0 | 1>(index: I) => FieldType<Extract<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }][I], FieldDefinition>["type"]>
>p : Point
>getIndex : <I extends 0 | 1>(index: I) => FieldType<Extract<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }][I], FieldDefinition>["type"]>
>2 : 2
p.setIndex(0, 0); // ok, 0 is a valid index
>p.setIndex(0, 0) : void
>p.setIndex : <I extends 0 | 1>(index: I, value: FieldType<Extract<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }][I], FieldDefinition>["type"]>) => void
>p : Point
>setIndex : <I extends 0 | 1>(index: I, value: FieldType<Extract<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }][I], FieldDefinition>["type"]>) => void
>0 : 0
>0 : 0
p.setIndex(1, 0); // ok, 1 is a valid index
>p.setIndex(1, 0) : void
>p.setIndex : <I extends 0 | 1>(index: I, value: FieldType<Extract<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }][I], FieldDefinition>["type"]>) => void
>p : Point
>setIndex : <I extends 0 | 1>(index: I, value: FieldType<Extract<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }][I], FieldDefinition>["type"]>) => void
>1 : 1
>0 : 0
p.setIndex(2, 3); // error, 2 is not a valid index
>p.setIndex(2, 3) : void
>p.setIndex : <I extends 0 | 1>(index: I, value: FieldType<Extract<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }][I], FieldDefinition>["type"]>) => void
>p : Point
>setIndex : <I extends 0 | 1>(index: I, value: FieldType<Extract<[{ name: "x"; type: "f64"; }, { name: "y"; type: "f64"; }][I], FieldDefinition>["type"]>) => void
>2 : 2
>3 : 3
// function inference
declare function f1<T extends string | number>(s: `**${T}**`): T;
>f1 : <T extends string | number>(s: `**${T}**`) => T
>s : `**${T}**`
f1("**123**"); // "123"
>f1("**123**") : "123"
>f1 : <T extends string | number>(s: `**${T}**`) => T
>"**123**" : "**123**"
declare function f2<T extends number>(s: `**${T}**`): T;
>f2 : <T extends number>(s: `**${T}**`) => T
>s : `**${T}**`
f2("**123**"); // 123
>f2("**123**") : 123
>f2 : <T extends number>(s: `**${T}**`) => T
>"**123**" : "**123**"
declare function f3<T extends bigint>(s: `**${T}**`): T;
>f3 : <T extends bigint>(s: `**${T}**`) => T
>s : `**${T}**`
f3("**123**"); // 123n
>f3("**123**") : 123n
>f3 : <T extends bigint>(s: `**${T}**`) => T
>"**123**" : "**123**"
declare function f4<T extends boolean>(s: `**${T}**`): T;
>f4 : <T extends boolean>(s: `**${T}**`) => T
>s : `**${T}**`
f4("**true**"); // true | "true"
>f4("**true**") : true
>f4 : <T extends boolean>(s: `**${T}**`) => T
>"**true**" : "**true**"
f4("**false**"); // false | "false"
>f4("**false**") : false
>f4 : <T extends boolean>(s: `**${T}**`) => T
>"**false**" : "**false**"

Some files were not shown because too many files have changed in this diff Show More