From e7399fbb66ec8e2ed84abd9918917256475f40bd Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 11 Jun 2024 11:08:45 -0700 Subject: [PATCH 1/2] Allow `satisfies keyof` assertions in computed property names --- src/compiler/checker.ts | 80 +- src/compiler/diagnosticMessages.json | 8 + src/compiler/parser.ts | 4 +- src/compiler/transformers/declarations.ts | 27 +- src/compiler/types.ts | 12 +- src/compiler/utilities.ts | 7 + tests/baselines/reference/api/typescript.d.ts | 2 +- .../baselines/reference/indexTypeCheck.types | 2 +- .../reference/indexWithUndefinedAndNull.types | 4 +- ...WithUndefinedAndNullStrictNullChecks.types | 4 +- .../baselines/reference/propertyAccess.types | 8 +- .../reference/satisfiesKeyof1.errors.txt | 50 ++ tests/baselines/reference/satisfiesKeyof1.js | 86 ++ .../reference/satisfiesKeyof1.symbols | 72 ++ .../baselines/reference/satisfiesKeyof1.types | 142 +++ .../satisfiesKeyofGenerics.errors.txt | 183 ++++ .../reference/satisfiesKeyofGenerics.js | 233 +++++ .../reference/satisfiesKeyofGenerics.symbols | 296 +++++++ .../reference/satisfiesKeyofGenerics.types | 460 ++++++++++ .../satisfiesKeyofInputTypes.errors.txt | 266 ++++++ .../reference/satisfiesKeyofInputTypes.js | 356 ++++++++ .../satisfiesKeyofInputTypes.symbols | 404 +++++++++ .../reference/satisfiesKeyofInputTypes.types | 828 ++++++++++++++++++ .../types/keyof/satisfiesKeyof1.ts | 36 + .../types/keyof/satisfiesKeyofGenerics.ts | 112 +++ .../types/keyof/satisfiesKeyofInputTypes.ts | 162 ++++ 26 files changed, 3818 insertions(+), 26 deletions(-) create mode 100644 tests/baselines/reference/satisfiesKeyof1.errors.txt create mode 100644 tests/baselines/reference/satisfiesKeyof1.js create mode 100644 tests/baselines/reference/satisfiesKeyof1.symbols create mode 100644 tests/baselines/reference/satisfiesKeyof1.types create mode 100644 tests/baselines/reference/satisfiesKeyofGenerics.errors.txt create mode 100644 tests/baselines/reference/satisfiesKeyofGenerics.js create mode 100644 tests/baselines/reference/satisfiesKeyofGenerics.symbols create mode 100644 tests/baselines/reference/satisfiesKeyofGenerics.types create mode 100644 tests/baselines/reference/satisfiesKeyofInputTypes.errors.txt create mode 100644 tests/baselines/reference/satisfiesKeyofInputTypes.js create mode 100644 tests/baselines/reference/satisfiesKeyofInputTypes.symbols create mode 100644 tests/baselines/reference/satisfiesKeyofInputTypes.types create mode 100644 tests/cases/conformance/types/keyof/satisfiesKeyof1.ts create mode 100644 tests/cases/conformance/types/keyof/satisfiesKeyofGenerics.ts create mode 100644 tests/cases/conformance/types/keyof/satisfiesKeyofInputTypes.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 51bbd6295c4ca..37413269764d4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1109,6 +1109,7 @@ import { WideningContext, WithStatement, YieldExpression, + isSatisfiesKeyofExpression, } from "./_namespaces/ts.js"; import * as moduleSpecifiers from "./_namespaces/ts.moduleSpecifiers.js"; import * as performance from "./_namespaces/ts.performance.js"; @@ -5863,7 +5864,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { entityName.parent.kind === SyntaxKind.TypeQuery || entityName.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isPartOfTypeNode(entityName.parent) || entityName.parent.kind === SyntaxKind.ComputedPropertyName || - entityName.parent.kind === SyntaxKind.TypePredicate && (entityName.parent as TypePredicateNode).parameterName === entityName + entityName.parent.kind === SyntaxKind.TypePredicate && (entityName.parent as TypePredicateNode).parameterName === entityName || + isSatisfiesKeyofExpression(entityName.parent) ) { // Typeof value meaning = SymbolFlags.Value | SymbolFlags.ExportValue; @@ -7061,7 +7063,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else { - trackComputedName(decl.name.expression, saveEnclosingDeclaration, context); + trackComputedName(isEntityNameExpression(decl.name.expression) ? decl.name.expression : decl.name.expression.expression, saveEnclosingDeclaration, context); } } } @@ -7601,7 +7603,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return elideInitializerAndSetEmitFlags(node) as BindingName; function elideInitializerAndSetEmitFlags(node: Node): Node { if (context.tracker.canTrackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) { - trackComputedName(node.expression, context.enclosingDeclaration, context); + trackComputedName(isEntityNameExpression(node.expression) ? node.expression : node.expression.expression, context.enclosingDeclaration, context); } let visited = visitEachChildWorker(node, elideInitializerAndSetEmitFlags, /*context*/ undefined, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags); if (isBindingElement(visited)) { @@ -13204,7 +13206,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isComputedPropertyName(node) && !isElementAccessExpression(node)) { return false; } - const expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression; + let expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression; + if (isSatisfiesExpression(expr) && expr.type.kind === SyntaxKind.KeyOfKeyword) { + expr = expr.expression; + } return isEntityNameExpression(expr) && isTypeUsableAsPropertyName(isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached(expr)); } @@ -19623,6 +19628,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type; } + function getUniqueESSymbolTypeForSymbol(symbol: Symbol) { + const links = getSymbolLinks(symbol); + if (!links.uniqueESSymbolType) { + links.uniqueESSymbolType = createUniqueESSymbolType(symbol); + } + return links.uniqueESSymbolType; + } + function getESSymbolLikeTypeForNode(node: Node) { if (isInJSFile(node) && isJSDocTypeExpression(node)) { const host = getJSDocHost(node); @@ -19633,8 +19646,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isValidESSymbolDeclaration(node)) { const symbol = isCommonJsExportPropertyAssignment(node) ? getSymbolOfNode((node as BinaryExpression).left) : getSymbolOfNode(node); if (symbol) { - const links = getSymbolLinks(symbol); - return links.uniqueESSymbolType || (links.uniqueESSymbolType = createUniqueESSymbolType(symbol)); + return getUniqueESSymbolTypeForSymbol(symbol); } } return esSymbolType; @@ -19706,6 +19718,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { addOptionality(getTypeFromTypeNode(node.type), /*isProperty*/ true, !!node.questionToken)); } + function getTypeFromKeyofKeywordTypeNode(node: KeywordTypeNode) { + if (!isSatisfiesExpression(node.parent) || !isComputedPropertyName(node.parent.parent)) { + error(node, Diagnostics.keyof_type_must_have_an_operand_type); + } + return stringNumberSymbolType; // used to contextually type the LHS of the `satisfies` and ensures literals get literal types + } + function getTypeFromTypeNode(node: TypeNode): Type { return getConditionalFlowTypeOfType(getTypeFromTypeNodeWorker(node), node); } @@ -19807,6 +19826,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.PropertyAccessExpression as TypeNodeSyntaxKind: const symbol = getSymbolAtLocation(node); return symbol ? getDeclaredTypeOfSymbol(symbol) : errorType; + case SyntaxKind.KeyOfKeyword: + return getTypeFromKeyofKeywordTypeNode(node as KeywordTypeNode); default: return errorType; } @@ -34552,7 +34573,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } const indexedAccessType = getIndexedAccessTypeOrUndefined(objectType, effectiveIndexType, accessFlags, node) || errorType; - return checkIndexedAccessIndexType(getFlowTypeOfAccessExpression(node, getNodeLinks(node).resolvedSymbol, indexedAccessType, indexExpression, checkMode), node); + const result = checkIndexedAccessIndexType(getFlowTypeOfAccessExpression(node, getNodeLinks(node).resolvedSymbol, indexedAccessType, indexExpression, checkMode), node); + if (!isErrorType(result)) { + return result; + } + // lookup failed, try fallback without error reporting for more accurate type than `any` + if (isEntityNameExpression(indexExpression)) { + const fallback = getResolvedEntityNameUniqueSymbolType(indexExpression); + if (fallback) { + const indexedAccessType = getIndexedAccessTypeOrUndefined(objectType, fallback, accessFlags) || errorType; + // If the lookup simplifies/resolves, return it + if (!isErrorType(indexedAccessType) && !(indexedAccessType.flags & TypeFlags.IndexedAccess && (indexedAccessType as IndexedAccessType).objectType === objectType && (indexedAccessType as IndexedAccessType).indexType === fallback)) { + return getFlowTypeOfAccessExpression(node, getNodeLinks(node).resolvedSymbol, indexedAccessType, indexExpression, checkMode); + } + } + } + return result; } function callLikeExpressionMayHaveTypeArguments(node: CallLikeExpression): node is CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement { @@ -37163,13 +37199,41 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return checkSatisfiesExpressionWorker(node.expression, node.type); } + function getResolvedEntityNameUniqueSymbolType(expression: EntityNameExpression): Type | undefined { + const links = getNodeLinks(expression); + if (!links.uniqueSymbollFallback) { + let resolved = resolveEntityName(expression, SymbolFlags.Value | SymbolFlags.ExportValue, /*ignoreErrors*/ true); + if (!resolved || resolved === unknownSymbol) { + resolved = resolveEntityName(expression, SymbolFlags.Value | SymbolFlags.ExportValue, /*ignoreErrors*/ true, /*dontResolveAlias*/ true); + } + if (resolved) { + // overwrite to `unique symbol` type for reference, so it actually works as a property, despite the type error + links.uniqueSymbollFallback = getUniqueESSymbolTypeForSymbol(resolved); + } + else { + // reference does not resolve, do nothing + links.uniqueSymbollFallback = false; + } + } + return links.uniqueSymbollFallback || undefined; + } + function checkSatisfiesExpressionWorker(expression: Expression, target: TypeNode, checkMode?: CheckMode) { const exprType = checkExpression(expression, checkMode); + const errorNode = findAncestor(target.parent, n => n.kind === SyntaxKind.SatisfiesExpression || n.kind === SyntaxKind.JSDocSatisfiesTag); + if (target.kind === SyntaxKind.KeyOfKeyword && isComputedPropertyName(expression.parent.parent)) { + if (!(exprType.flags & TypeFlags.StringOrNumberLiteralOrUnique)) { + error(expression, Diagnostics.A_satisfies_keyof_computed_property_name_must_be_exactly_a_single_string_number_or_unique_symbol_literal_type); + if (isEntityNameExpression(expression)) { + return getResolvedEntityNameUniqueSymbolType(expression) || exprType; + } + } + return exprType; + } const targetType = getTypeFromTypeNode(target); if (isErrorType(targetType)) { return targetType; } - const errorNode = findAncestor(target.parent, n => n.kind === SyntaxKind.SatisfiesExpression || n.kind === SyntaxKind.JSDocSatisfiesTag); checkTypeAssignableToAndOptionallyElaborate(exprType, targetType, errorNode, expression, Diagnostics.Type_0_does_not_satisfy_the_expected_type_1); return exprType; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index e74033719b5b8..4a2254550adbc 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -7030,6 +7030,14 @@ "category": "Error", "code": 9039 }, + "`keyof` type must have an operand type.": { + "category": "Error", + "code": 9040 + }, + "A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type.": { + "category": "Error", + "code": 9041 + }, "JSX attributes must only be assigned a non-empty 'expression'.": { "category": "Error", "code": 17000 diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 56b958bcf3b74..768d219cb70f4 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4729,7 +4729,9 @@ namespace Parser { function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword) { const pos = getNodePos(); parseExpected(operator); - return finishNode(factory.createTypeOperatorNode(operator, parseTypeOperatorOrHigher()), pos); + const arg = operator !== SyntaxKind.KeyOfKeyword || isStartOfType() ? parseTypeOperatorOrHigher() : undefined; + // parse `keyof` with no argument as a `keyof` keyword type node + return finishNode(arg ? factory.createTypeOperatorNode(operator, arg) : factory.createKeywordTypeNode(SyntaxKind.KeyOfKeyword), pos); } function tryParseConstraintOfInferType() { diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 14c90c911039e..1343fc9e1a46d 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -13,6 +13,7 @@ import { canProduceDiagnostics, ClassDeclaration, compact, + ComputedPropertyName, concatenate, ConditionalTypeNode, ConstructorDeclaration, @@ -128,6 +129,7 @@ import { isOmittedExpression, isPrimitiveLiteralValue, isPrivateIdentifier, + isSatisfiesKeyofExpression, isSemicolonClassElement, isSetAccessorDeclaration, isSourceFile, @@ -147,6 +149,7 @@ import { isVariableDeclaration, isVarUsing, LateBoundDeclaration, + LateBoundName, LateVisibilityPaintedStatement, length, map, @@ -159,6 +162,7 @@ import { ModuleBody, ModuleDeclaration, ModuleName, + Mutable, NamedDeclaration, NamespaceDeclaration, needsScopeMarker, @@ -1000,7 +1004,7 @@ export function transformDeclarations(context: TransformationContext) { if (isolatedDeclarations) { // Classes and object literals usually elide properties with computed names that are not of a literal type // In isolated declarations TSC needs to error on these as we don't know the type in a DTE. - if (!resolver.isDefinitelyReferenceToGlobalSymbolObject(input.name.expression)) { + if (!resolver.isDefinitelyReferenceToGlobalSymbolObject(input.name.expression) && !isSatisfiesKeyofExpression(input.name.expression)) { if (isClassDeclaration(input.parent) || isObjectLiteralExpression(input.parent)) { context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations)); return; @@ -1015,7 +1019,7 @@ export function transformDeclarations(context: TransformationContext) { } } } - else if (!resolver.isLateBound(getParseTreeNode(input) as Declaration) || !isEntityNameExpression(input.name.expression)) { + else if (!resolver.isLateBound(getParseTreeNode(input) as Declaration) || !(isEntityNameExpression(input.name.expression) || isSatisfiesKeyofExpression(input.name.expression))) { return; } } @@ -1259,7 +1263,10 @@ export function transformDeclarations(context: TransformationContext) { function cleanup(returnValue: T | undefined): T | undefined { if (returnValue && canProduceDiagnostic && hasDynamicName(input as Declaration)) { - checkName(input); + const updated = checkName(input, returnValue); + if (updated) { + returnValue = updated; + } } if (isEnclosingDeclaration(input)) { enclosingDeclaration = previousEnclosingDeclaration; @@ -1782,7 +1789,7 @@ export function transformDeclarations(context: TransformationContext) { } } - function checkName(node: DeclarationDiagnosticProducing) { + function checkName(node: DeclarationDiagnosticProducing, returnValue: T | undefined): T | undefined { let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined; if (!suppressNewDiagnosticContexts) { oldDiag = getSymbolAccessibilityDiagnostic; @@ -1792,11 +1799,21 @@ export function transformDeclarations(context: TransformationContext) { Debug.assert(hasDynamicName(node as NamedDeclaration)); // Should only be called with dynamic names const decl = node as NamedDeclaration as LateBoundDeclaration; const entityName = decl.name.expression; - checkEntityNameVisibility(entityName, enclosingDeclaration); + const nameExpr = isEntityNameExpression(entityName) ? entityName : entityName.expression; + checkEntityNameVisibility(nameExpr, enclosingDeclaration); + let result = returnValue; + if (returnValue && nameExpr !== entityName) { + const updated = factory.updateComputedPropertyName(decl.name, nameExpr) as LateBoundName; + result = factory.cloneNode(returnValue); + (result as Mutable).name = updated as Extract["name"] & LateBoundName; + } if (!suppressNewDiagnosticContexts) { getSymbolAccessibilityDiagnostic = oldDiag!; } errorNameNode = undefined; + if (result as Node as T !== returnValue) { + return result as Node as T; + } } function shouldStripInternal(node: Node) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 7388c9c94e235..12d9cda24f748 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -691,7 +691,8 @@ export type KeywordTypeSyntaxKind = | SyntaxKind.SymbolKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UnknownKeyword - | SyntaxKind.VoidKeyword; + | SyntaxKind.VoidKeyword + | SyntaxKind.KeyOfKeyword; /** @internal */ export type TypeNodeSyntaxKind = @@ -1790,10 +1791,16 @@ export interface GeneratedPrivateIdentifier extends PrivateIdentifier { readonly emitNode: EmitNode & { autoGenerate: AutoGenerateInfo; }; } +/** @internal */ +export interface SatisfiesKeyofEntityNameExpression extends SatisfiesExpression { + readonly expression: EntityNameExpression; + readonly type: KeywordTypeNode; +} + /** @internal */ // A name that supports late-binding (used in checker) export interface LateBoundName extends ComputedPropertyName { - readonly expression: EntityNameExpression; + readonly expression: EntityNameExpression | SatisfiesKeyofEntityNameExpression; } export interface Decorator extends Node { @@ -6176,6 +6183,7 @@ export interface NodeLinks { fakeScopeForSignatureDeclaration?: "params" | "typeParams"; // If present, this is a fake scope injected into an enclosing declaration chain. assertionExpressionType?: Type; // Cached type of the expression of a type assertion externalHelpersModule?: Symbol; // Resolved symbol for the external helpers module + uniqueSymbollFallback?: Type | false;// Cached type of type node } /** @internal */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c7170af2355a4..8170ee721fe82 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -585,6 +585,7 @@ import { WriteFileCallback, WriteFileCallbackData, YieldExpression, + SatisfiesKeyofEntityNameExpression, } from "./_namespaces/ts.js"; /** @internal */ @@ -11664,3 +11665,9 @@ export function hasInferredType(node: Node): node is HasInferredType { return false; } } + +/** @internal */ +export function isSatisfiesKeyofExpression(node: Node): node is SatisfiesKeyofEntityNameExpression { + return node.kind === SyntaxKind.SatisfiesExpression && (node as SatisfiesExpression).type.kind === SyntaxKind.KeyOfKeyword && isEntityNameExpression((node as SatisfiesExpression).expression); + +} \ No newline at end of file diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index a4903113b8dff..31f8b03dcde5b 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4190,7 +4190,7 @@ declare namespace ts { | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; type ModifierSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AccessorKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.ConstKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.ExportKeyword | SyntaxKind.InKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.OutKeyword | SyntaxKind.OverrideKeyword | SyntaxKind.StaticKeyword; - type KeywordTypeSyntaxKind = SyntaxKind.AnyKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.IntrinsicKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.StringKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VoidKeyword; + type KeywordTypeSyntaxKind = SyntaxKind.AnyKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.IntrinsicKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.StringKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VoidKeyword | SyntaxKind.KeyOfKeyword; type TokenSyntaxKind = SyntaxKind.Unknown | SyntaxKind.EndOfFileToken | TriviaSyntaxKind | LiteralSyntaxKind | PseudoLiteralSyntaxKind | PunctuationSyntaxKind | SyntaxKind.Identifier | KeywordSyntaxKind; type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.OpenParenToken | SyntaxKind.CloseParenToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.HashToken | SyntaxKind.Unknown | KeywordSyntaxKind; diff --git a/tests/baselines/reference/indexTypeCheck.types b/tests/baselines/reference/indexTypeCheck.types index 57eb19d179acc..38dfba1197c7a 100644 --- a/tests/baselines/reference/indexTypeCheck.types +++ b/tests/baselines/reference/indexTypeCheck.types @@ -142,7 +142,7 @@ s[{}]; // ok > : ^^ yellow[blue]; // error ->yellow[blue] : any +>yellow[blue] : Red > : ^^^ >yellow : Yellow > : ^^^^^^ diff --git a/tests/baselines/reference/indexWithUndefinedAndNull.types b/tests/baselines/reference/indexWithUndefinedAndNull.types index 7a95b2db85abc..b5c921881078b 100644 --- a/tests/baselines/reference/indexWithUndefinedAndNull.types +++ b/tests/baselines/reference/indexWithUndefinedAndNull.types @@ -42,8 +42,8 @@ str = n[null]; let num: number = s[undefined]; >num : number > : ^^^^^^ ->s[undefined] : any -> : ^^^ +>s[undefined] : number +> : ^^^^^^ >s : S > : ^ >undefined : undefined diff --git a/tests/baselines/reference/indexWithUndefinedAndNullStrictNullChecks.types b/tests/baselines/reference/indexWithUndefinedAndNullStrictNullChecks.types index 5a76b7ee48d1a..72cb2cff03ece 100644 --- a/tests/baselines/reference/indexWithUndefinedAndNullStrictNullChecks.types +++ b/tests/baselines/reference/indexWithUndefinedAndNullStrictNullChecks.types @@ -42,8 +42,8 @@ str = n[null]; let num: number = s[undefined]; >num : number > : ^^^^^^ ->s[undefined] : any -> : ^^^ +>s[undefined] : number +> : ^^^^^^ >s : S > : ^ >undefined : undefined diff --git a/tests/baselines/reference/propertyAccess.types b/tests/baselines/reference/propertyAccess.types index 4d8b083563337..2954753fcc19e 100644 --- a/tests/baselines/reference/propertyAccess.types +++ b/tests/baselines/reference/propertyAccess.types @@ -607,10 +607,10 @@ var zz: A; // Bracket notation property access using value of other type on type with numeric index signature and no string index signature and string index signature var zzzz = bothIndex[someObject]; // Error ->zzzz : any -> : ^^^ ->bothIndex[someObject] : any -> : ^^^ +>zzzz : A +> : ^ +>bothIndex[someObject] : A +> : ^ >bothIndex : { [n: string]: A; [m: number]: B; } > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >someObject : { name: string; } diff --git a/tests/baselines/reference/satisfiesKeyof1.errors.txt b/tests/baselines/reference/satisfiesKeyof1.errors.txt new file mode 100644 index 0000000000000..68ed4f5af644f --- /dev/null +++ b/tests/baselines/reference/satisfiesKeyof1.errors.txt @@ -0,0 +1,50 @@ +satisfiesKeyof1.ts(13,17): error TS2792: Cannot find module 'missing'. Did you mean to set the 'moduleResolution' option to 'nodenext', or to add aliases to the 'paths' option? +satisfiesKeyof1.ts(15,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyof1.ts(25,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyof1.ts(34,30): error TS9040: `keyof` type must have an operand type. + + +==== satisfiesKeyof1.ts (4 errors) ==== + // intended usage + const x = Symbol(); + + export class Foo { + [x satisfies keyof]() { + return 1; + } + } + + export const usage1 = new Foo()[x](); + + // errors on missing + import {y} from "missing"; + ~~~~~~~~~ +!!! error TS2792: Cannot find module 'missing'. Did you mean to set the 'moduleResolution' option to 'nodenext', or to add aliases to the 'paths' option? + export class Bar { + [y satisfies keyof]() { + ~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 1; + } + } + + export const usage2 = new Bar()[y](); + + // errors on wrong types + const z = Math.random() ? 1 : "a"; + export class Baz { + [z satisfies keyof]() { + ~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 1; + } + } + + export const usage3 = new Baz()[z](); + + // error on satisfies keyof outside computed name + + export const a = 0 satisfies keyof; + ~~~~~ +!!! error TS9040: `keyof` type must have an operand type. + \ No newline at end of file diff --git a/tests/baselines/reference/satisfiesKeyof1.js b/tests/baselines/reference/satisfiesKeyof1.js new file mode 100644 index 0000000000000..b1e7d5dbe831a --- /dev/null +++ b/tests/baselines/reference/satisfiesKeyof1.js @@ -0,0 +1,86 @@ +//// [tests/cases/conformance/types/keyof/satisfiesKeyof1.ts] //// + +//// [satisfiesKeyof1.ts] +// intended usage +const x = Symbol(); + +export class Foo { + [x satisfies keyof]() { + return 1; + } +} + +export const usage1 = new Foo()[x](); + +// errors on missing +import {y} from "missing"; +export class Bar { + [y satisfies keyof]() { + return 1; + } +} + +export const usage2 = new Bar()[y](); + +// errors on wrong types +const z = Math.random() ? 1 : "a"; +export class Baz { + [z satisfies keyof]() { + return 1; + } +} + +export const usage3 = new Baz()[z](); + +// error on satisfies keyof outside computed name + +export const a = 0 satisfies keyof; + + +//// [satisfiesKeyof1.js] +// intended usage +const x = Symbol(); +export class Foo { + [x]() { + return 1; + } +} +export const usage1 = new Foo()[x](); +// errors on missing +import { y } from "missing"; +export class Bar { + [y]() { + return 1; + } +} +export const usage2 = new Bar()[y](); +// errors on wrong types +const z = Math.random() ? 1 : "a"; +export class Baz { + [z]() { + return 1; + } +} +export const usage3 = new Baz()[z](); +// error on satisfies keyof outside computed name +export const a = 0; + + +//// [satisfiesKeyof1.d.ts] +declare const x: unique symbol; +export declare class Foo { + [x](): number; +} +export declare const usage1: number; +import { y } from "missing"; +export declare class Bar { + [y](): number; +} +export declare const usage2: number; +declare const z: string | number; +export declare class Baz { + [z](): number; +} +export declare const usage3: number; +export declare const a = 0; +export {}; diff --git a/tests/baselines/reference/satisfiesKeyof1.symbols b/tests/baselines/reference/satisfiesKeyof1.symbols new file mode 100644 index 0000000000000..9938edc4a47f7 --- /dev/null +++ b/tests/baselines/reference/satisfiesKeyof1.symbols @@ -0,0 +1,72 @@ +//// [tests/cases/conformance/types/keyof/satisfiesKeyof1.ts] //// + +=== satisfiesKeyof1.ts === +// intended usage +const x = Symbol(); +>x : Symbol(x, Decl(satisfiesKeyof1.ts, 1, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +export class Foo { +>Foo : Symbol(Foo, Decl(satisfiesKeyof1.ts, 1, 19)) + + [x satisfies keyof]() { +>[x satisfies keyof] : Symbol(Foo[x satisfies keyof], Decl(satisfiesKeyof1.ts, 3, 18)) +>x : Symbol(x, Decl(satisfiesKeyof1.ts, 1, 5)) + + return 1; + } +} + +export const usage1 = new Foo()[x](); +>usage1 : Symbol(usage1, Decl(satisfiesKeyof1.ts, 9, 12)) +>Foo : Symbol(Foo, Decl(satisfiesKeyof1.ts, 1, 19)) +>x : Symbol(x, Decl(satisfiesKeyof1.ts, 1, 5)) + +// errors on missing +import {y} from "missing"; +>y : Symbol(y, Decl(satisfiesKeyof1.ts, 12, 8)) + +export class Bar { +>Bar : Symbol(Bar, Decl(satisfiesKeyof1.ts, 12, 26)) + + [y satisfies keyof]() { +>[y satisfies keyof] : Symbol(Bar[y satisfies keyof], Decl(satisfiesKeyof1.ts, 13, 18)) +>y : Symbol(y, Decl(satisfiesKeyof1.ts, 12, 8)) + + return 1; + } +} + +export const usage2 = new Bar()[y](); +>usage2 : Symbol(usage2, Decl(satisfiesKeyof1.ts, 19, 12)) +>Bar : Symbol(Bar, Decl(satisfiesKeyof1.ts, 12, 26)) +>y : Symbol(y, Decl(satisfiesKeyof1.ts, 12, 8)) + +// errors on wrong types +const z = Math.random() ? 1 : "a"; +>z : Symbol(z, Decl(satisfiesKeyof1.ts, 22, 5)) +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + +export class Baz { +>Baz : Symbol(Baz, Decl(satisfiesKeyof1.ts, 22, 34)) + + [z satisfies keyof]() { +>[z satisfies keyof] : Symbol(Baz[z satisfies keyof], Decl(satisfiesKeyof1.ts, 23, 18)) +>z : Symbol(z, Decl(satisfiesKeyof1.ts, 22, 5)) + + return 1; + } +} + +export const usage3 = new Baz()[z](); +>usage3 : Symbol(usage3, Decl(satisfiesKeyof1.ts, 29, 12)) +>Baz : Symbol(Baz, Decl(satisfiesKeyof1.ts, 22, 34)) +>z : Symbol(z, Decl(satisfiesKeyof1.ts, 22, 5)) + +// error on satisfies keyof outside computed name + +export const a = 0 satisfies keyof; +>a : Symbol(a, Decl(satisfiesKeyof1.ts, 33, 12)) + diff --git a/tests/baselines/reference/satisfiesKeyof1.types b/tests/baselines/reference/satisfiesKeyof1.types new file mode 100644 index 0000000000000..ccf42412362f0 --- /dev/null +++ b/tests/baselines/reference/satisfiesKeyof1.types @@ -0,0 +1,142 @@ +//// [tests/cases/conformance/types/keyof/satisfiesKeyof1.ts] //// + +=== satisfiesKeyof1.ts === +// intended usage +const x = Symbol(); +>x : unique symbol +> : ^^^^^^^^^^^^^ +>Symbol() : unique symbol +> : ^^^^^^^^^^^^^ +>Symbol : SymbolConstructor +> : ^^^^^^^^^^^^^^^^^ + +export class Foo { +>Foo : Foo +> : ^^^ + + [x satisfies keyof]() { +>[x satisfies keyof] : () => number +> : ^^^^^^^^^^^^ +>x satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>x : unique symbol +> : ^^^^^^^^^^^^^ + + return 1; +>1 : 1 +> : ^ + } +} + +export const usage1 = new Foo()[x](); +>usage1 : number +> : ^^^^^^ +>new Foo()[x]() : number +> : ^^^^^^ +>new Foo()[x] : () => number +> : ^^^^^^^^^^^^ +>new Foo() : Foo +> : ^^^ +>Foo : typeof Foo +> : ^^^^^^^^^^ +>x : unique symbol +> : ^^^^^^^^^^^^^ + +// errors on missing +import {y} from "missing"; +>y : any +> : ^^^ + +export class Bar { +>Bar : Bar +> : ^^^ + + [y satisfies keyof]() { +>[y satisfies keyof] : () => number +> : ^^^^^^^^^^^^ +>y satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>y : any +> : ^^^ + + return 1; +>1 : 1 +> : ^ + } +} + +export const usage2 = new Bar()[y](); +>usage2 : number +> : ^^^^^^ +>new Bar()[y]() : number +> : ^^^^^^ +>new Bar()[y] : () => number +> : ^^^^^^^^^^^^ +>new Bar() : Bar +> : ^^^ +>Bar : typeof Bar +> : ^^^^^^^^^^ +>y : any +> : ^^^ + +// errors on wrong types +const z = Math.random() ? 1 : "a"; +>z : 1 | "a" +> : ^^^^^^^ +>Math.random() ? 1 : "a" : 1 | "a" +> : ^^^^^^^ +>Math.random() : number +> : ^^^^^^ +>Math.random : () => number +> : ^^^^^^ +>Math : Math +> : ^^^^ +>random : () => number +> : ^^^^^^ +>1 : 1 +> : ^ +>"a" : "a" +> : ^^^ + +export class Baz { +>Baz : Baz +> : ^^^ + + [z satisfies keyof]() { +>[z satisfies keyof] : () => number +> : ^^^^^^^^^^^^ +>z satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>z : 1 | "a" +> : ^^^^^^^ + + return 1; +>1 : 1 +> : ^ + } +} + +export const usage3 = new Baz()[z](); +>usage3 : number +> : ^^^^^^ +>new Baz()[z]() : number +> : ^^^^^^ +>new Baz()[z] : () => number +> : ^^^^^^^^^^^^ +>new Baz() : Baz +> : ^^^ +>Baz : typeof Baz +> : ^^^^^^^^^^ +>z : 1 | "a" +> : ^^^^^^^ + +// error on satisfies keyof outside computed name + +export const a = 0 satisfies keyof; +>a : 0 +> : ^ +>0 satisfies keyof : 0 +> : ^ +>0 : 0 +> : ^ + diff --git a/tests/baselines/reference/satisfiesKeyofGenerics.errors.txt b/tests/baselines/reference/satisfiesKeyofGenerics.errors.txt new file mode 100644 index 0000000000000..b0aca465f11cd --- /dev/null +++ b/tests/baselines/reference/satisfiesKeyofGenerics.errors.txt @@ -0,0 +1,183 @@ +satisfiesKeyofGenerics.ts(37,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(40,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(43,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(46,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(49,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(52,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(55,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(58,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(61,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(64,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(67,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(70,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(73,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(76,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(79,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(82,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(85,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(88,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(91,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(94,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(100,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(103,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofGenerics.ts(106,14): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + + +==== satisfiesKeyofGenerics.ts (23 errors) ==== + export function f< + T, + U extends string, + V extends "onefield", + W extends "afield" | "bfield", + >( + p1: T, + p2: T & string, + p3: T & "f", + p4: T | string, + p5: T | "g", + p6: Extract, + + p7: U, + p8: U & string, + p9: U & "f", + p10: U | string, + p11: U | "g", + p12: Extract, + + p13: V, + p14: V & string, + p15: V & "onefield", + p16: V | string, + p17: V | "onefield", + p18: Extract, + + p19: W, + p20: W & string, + p21: W & "afield", // reduction rules for generics extending unions will simplify this to just "afield" where possible, so should be the only one that works without error + p22: W | string, + p23: W | "afield", + p24: Extract, + ) { + return [ + class Foo { + [p1 satisfies keyof]() { + ~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 1 as const; + } + [p2 satisfies keyof]() { + ~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 2 as const; + } + [p3 satisfies keyof]() { + ~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 3 as const; + } + [p4 satisfies keyof]() { + ~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 4 as const; + } + [p5 satisfies keyof]() { + ~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 5 as const; + } + [p6 satisfies keyof]() { + ~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 6 as const; + } + [p7 satisfies keyof]() { + ~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 7 as const; + } + [p8 satisfies keyof]() { + ~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 8 as const; + } + [p9 satisfies keyof]() { + ~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 9 as const; + } + [p10 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 10 as const; + } + [p11 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 11 as const; + } + [p12 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 12 as const; + } + [p13 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 13 as const; + } + [p14 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 14 as const; + } + [p15 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 15 as const; + } + [p16 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 16 as const; + } + [p17 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 17 as const; + } + [p18 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 18 as const; + } + [p19 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 19 as const; + } + [p20 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 20 as const; + } + [p21 satisfies keyof]() { + return 21 as const; + } + [p22 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 22 as const; + } + [p23 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 23 as const; + } + [p24 satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 24 as const; + } + } + ] as const; + } \ No newline at end of file diff --git a/tests/baselines/reference/satisfiesKeyofGenerics.js b/tests/baselines/reference/satisfiesKeyofGenerics.js new file mode 100644 index 0000000000000..7af8ab672fd6d --- /dev/null +++ b/tests/baselines/reference/satisfiesKeyofGenerics.js @@ -0,0 +1,233 @@ +//// [tests/cases/conformance/types/keyof/satisfiesKeyofGenerics.ts] //// + +//// [satisfiesKeyofGenerics.ts] +export function f< + T, + U extends string, + V extends "onefield", + W extends "afield" | "bfield", +>( + p1: T, + p2: T & string, + p3: T & "f", + p4: T | string, + p5: T | "g", + p6: Extract, + + p7: U, + p8: U & string, + p9: U & "f", + p10: U | string, + p11: U | "g", + p12: Extract, + + p13: V, + p14: V & string, + p15: V & "onefield", + p16: V | string, + p17: V | "onefield", + p18: Extract, + + p19: W, + p20: W & string, + p21: W & "afield", // reduction rules for generics extending unions will simplify this to just "afield" where possible, so should be the only one that works without error + p22: W | string, + p23: W | "afield", + p24: Extract, +) { + return [ + class Foo { + [p1 satisfies keyof]() { + return 1 as const; + } + [p2 satisfies keyof]() { + return 2 as const; + } + [p3 satisfies keyof]() { + return 3 as const; + } + [p4 satisfies keyof]() { + return 4 as const; + } + [p5 satisfies keyof]() { + return 5 as const; + } + [p6 satisfies keyof]() { + return 6 as const; + } + [p7 satisfies keyof]() { + return 7 as const; + } + [p8 satisfies keyof]() { + return 8 as const; + } + [p9 satisfies keyof]() { + return 9 as const; + } + [p10 satisfies keyof]() { + return 10 as const; + } + [p11 satisfies keyof]() { + return 11 as const; + } + [p12 satisfies keyof]() { + return 12 as const; + } + [p13 satisfies keyof]() { + return 13 as const; + } + [p14 satisfies keyof]() { + return 14 as const; + } + [p15 satisfies keyof]() { + return 15 as const; + } + [p16 satisfies keyof]() { + return 16 as const; + } + [p17 satisfies keyof]() { + return 17 as const; + } + [p18 satisfies keyof]() { + return 18 as const; + } + [p19 satisfies keyof]() { + return 19 as const; + } + [p20 satisfies keyof]() { + return 20 as const; + } + [p21 satisfies keyof]() { + return 21 as const; + } + [p22 satisfies keyof]() { + return 22 as const; + } + [p23 satisfies keyof]() { + return 23 as const; + } + [p24 satisfies keyof]() { + return 24 as const; + } + } + ] as const; +} + +//// [satisfiesKeyofGenerics.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.f = f; +function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, // reduction rules for generics extending unions will simplify this to just "afield" where possible, so should be the only one that works without error +p22, p23, p24) { + return [ + /** @class */ (function () { + function Foo() { + } + Foo.prototype[p1] = function () { + return 1; + }; + Foo.prototype[p2] = function () { + return 2; + }; + Foo.prototype[p3] = function () { + return 3; + }; + Foo.prototype[p4] = function () { + return 4; + }; + Foo.prototype[p5] = function () { + return 5; + }; + Foo.prototype[p6] = function () { + return 6; + }; + Foo.prototype[p7] = function () { + return 7; + }; + Foo.prototype[p8] = function () { + return 8; + }; + Foo.prototype[p9] = function () { + return 9; + }; + Foo.prototype[p10] = function () { + return 10; + }; + Foo.prototype[p11] = function () { + return 11; + }; + Foo.prototype[p12] = function () { + return 12; + }; + Foo.prototype[p13] = function () { + return 13; + }; + Foo.prototype[p14] = function () { + return 14; + }; + Foo.prototype[p15] = function () { + return 15; + }; + Foo.prototype[p16] = function () { + return 16; + }; + Foo.prototype[p17] = function () { + return 17; + }; + Foo.prototype[p18] = function () { + return 18; + }; + Foo.prototype[p19] = function () { + return 19; + }; + Foo.prototype[p20] = function () { + return 20; + }; + Foo.prototype[p21] = function () { + return 21; + }; + Foo.prototype[p22] = function () { + return 22; + }; + Foo.prototype[p23] = function () { + return 23; + }; + Foo.prototype[p24] = function () { + return 24; + }; + return Foo; + }()) + ]; +} + + +//// [satisfiesKeyofGenerics.d.ts] +export declare function f(p1: T, p2: T & string, p3: T & "f", p4: T | string, p5: T | "g", p6: Extract, p7: U, p8: U & string, p9: U & "f", p10: U | string, p11: U | "g", p12: Extract, p13: V, p14: V & string, p15: V & "onefield", p16: V | string, p17: V | "onefield", p18: Extract, p19: W, p20: W & string, p21: W & "afield", // reduction rules for generics extending unions will simplify this to just "afield" where possible, so should be the only one that works without error +p22: W | string, p23: W | "afield", p24: Extract): readonly [{ + new (): { + [p1](): 1; + [p2](): 2; + [p3](): 3; + [p4](): 4; + [p5](): 5; + [p6](): 6; + [p7](): 7; + [p8](): 8; + [p9](): 9; + [p10](): 10; + [p11](): 11; + [p12](): 12; + [p13](): 13; + [p14](): 14; + [p15](): 15; + [p16](): 16; + [p17](): 17; + [p18](): 18; + [p19](): 19; + [p20](): 20; + afield(): 21; + [p22](): 22; + [p23](): 23; + [p24](): 24; + }; +}]; diff --git a/tests/baselines/reference/satisfiesKeyofGenerics.symbols b/tests/baselines/reference/satisfiesKeyofGenerics.symbols new file mode 100644 index 0000000000000..4ca362584f743 --- /dev/null +++ b/tests/baselines/reference/satisfiesKeyofGenerics.symbols @@ -0,0 +1,296 @@ +//// [tests/cases/conformance/types/keyof/satisfiesKeyofGenerics.ts] //// + +=== satisfiesKeyofGenerics.ts === +export function f< +>f : Symbol(f, Decl(satisfiesKeyofGenerics.ts, 0, 0)) + + T, +>T : Symbol(T, Decl(satisfiesKeyofGenerics.ts, 0, 18)) + + U extends string, +>U : Symbol(U, Decl(satisfiesKeyofGenerics.ts, 1, 6)) + + V extends "onefield", +>V : Symbol(V, Decl(satisfiesKeyofGenerics.ts, 2, 21)) + + W extends "afield" | "bfield", +>W : Symbol(W, Decl(satisfiesKeyofGenerics.ts, 3, 25)) + +>( + p1: T, +>p1 : Symbol(p1, Decl(satisfiesKeyofGenerics.ts, 5, 2)) +>T : Symbol(T, Decl(satisfiesKeyofGenerics.ts, 0, 18)) + + p2: T & string, +>p2 : Symbol(p2, Decl(satisfiesKeyofGenerics.ts, 6, 10)) +>T : Symbol(T, Decl(satisfiesKeyofGenerics.ts, 0, 18)) + + p3: T & "f", +>p3 : Symbol(p3, Decl(satisfiesKeyofGenerics.ts, 7, 19)) +>T : Symbol(T, Decl(satisfiesKeyofGenerics.ts, 0, 18)) + + p4: T | string, +>p4 : Symbol(p4, Decl(satisfiesKeyofGenerics.ts, 8, 16)) +>T : Symbol(T, Decl(satisfiesKeyofGenerics.ts, 0, 18)) + + p5: T | "g", +>p5 : Symbol(p5, Decl(satisfiesKeyofGenerics.ts, 9, 19)) +>T : Symbol(T, Decl(satisfiesKeyofGenerics.ts, 0, 18)) + + p6: Extract, +>p6 : Symbol(p6, Decl(satisfiesKeyofGenerics.ts, 10, 16)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(satisfiesKeyofGenerics.ts, 0, 18)) + + p7: U, +>p7 : Symbol(p7, Decl(satisfiesKeyofGenerics.ts, 11, 24)) +>U : Symbol(U, Decl(satisfiesKeyofGenerics.ts, 1, 6)) + + p8: U & string, +>p8 : Symbol(p8, Decl(satisfiesKeyofGenerics.ts, 13, 10)) +>U : Symbol(U, Decl(satisfiesKeyofGenerics.ts, 1, 6)) + + p9: U & "f", +>p9 : Symbol(p9, Decl(satisfiesKeyofGenerics.ts, 14, 19)) +>U : Symbol(U, Decl(satisfiesKeyofGenerics.ts, 1, 6)) + + p10: U | string, +>p10 : Symbol(p10, Decl(satisfiesKeyofGenerics.ts, 15, 16)) +>U : Symbol(U, Decl(satisfiesKeyofGenerics.ts, 1, 6)) + + p11: U | "g", +>p11 : Symbol(p11, Decl(satisfiesKeyofGenerics.ts, 16, 20)) +>U : Symbol(U, Decl(satisfiesKeyofGenerics.ts, 1, 6)) + + p12: Extract, +>p12 : Symbol(p12, Decl(satisfiesKeyofGenerics.ts, 17, 17)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>U : Symbol(U, Decl(satisfiesKeyofGenerics.ts, 1, 6)) + + p13: V, +>p13 : Symbol(p13, Decl(satisfiesKeyofGenerics.ts, 18, 25)) +>V : Symbol(V, Decl(satisfiesKeyofGenerics.ts, 2, 21)) + + p14: V & string, +>p14 : Symbol(p14, Decl(satisfiesKeyofGenerics.ts, 20, 11)) +>V : Symbol(V, Decl(satisfiesKeyofGenerics.ts, 2, 21)) + + p15: V & "onefield", +>p15 : Symbol(p15, Decl(satisfiesKeyofGenerics.ts, 21, 20)) +>V : Symbol(V, Decl(satisfiesKeyofGenerics.ts, 2, 21)) + + p16: V | string, +>p16 : Symbol(p16, Decl(satisfiesKeyofGenerics.ts, 22, 24)) +>V : Symbol(V, Decl(satisfiesKeyofGenerics.ts, 2, 21)) + + p17: V | "onefield", +>p17 : Symbol(p17, Decl(satisfiesKeyofGenerics.ts, 23, 20)) +>V : Symbol(V, Decl(satisfiesKeyofGenerics.ts, 2, 21)) + + p18: Extract, +>p18 : Symbol(p18, Decl(satisfiesKeyofGenerics.ts, 24, 24)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>V : Symbol(V, Decl(satisfiesKeyofGenerics.ts, 2, 21)) + + p19: W, +>p19 : Symbol(p19, Decl(satisfiesKeyofGenerics.ts, 25, 32)) +>W : Symbol(W, Decl(satisfiesKeyofGenerics.ts, 3, 25)) + + p20: W & string, +>p20 : Symbol(p20, Decl(satisfiesKeyofGenerics.ts, 27, 11)) +>W : Symbol(W, Decl(satisfiesKeyofGenerics.ts, 3, 25)) + + p21: W & "afield", // reduction rules for generics extending unions will simplify this to just "afield" where possible, so should be the only one that works without error +>p21 : Symbol(p21, Decl(satisfiesKeyofGenerics.ts, 28, 20)) +>W : Symbol(W, Decl(satisfiesKeyofGenerics.ts, 3, 25)) + + p22: W | string, +>p22 : Symbol(p22, Decl(satisfiesKeyofGenerics.ts, 29, 22)) +>W : Symbol(W, Decl(satisfiesKeyofGenerics.ts, 3, 25)) + + p23: W | "afield", +>p23 : Symbol(p23, Decl(satisfiesKeyofGenerics.ts, 30, 20)) +>W : Symbol(W, Decl(satisfiesKeyofGenerics.ts, 3, 25)) + + p24: Extract, +>p24 : Symbol(p24, Decl(satisfiesKeyofGenerics.ts, 31, 22)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>W : Symbol(W, Decl(satisfiesKeyofGenerics.ts, 3, 25)) + +) { + return [ + class Foo { +>Foo : Symbol(Foo, Decl(satisfiesKeyofGenerics.ts, 34, 12)) + + [p1 satisfies keyof]() { +>[p1 satisfies keyof] : Symbol(Foo[p1 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 35, 19)) +>p1 : Symbol(p1, Decl(satisfiesKeyofGenerics.ts, 5, 2)) + + return 1 as const; +>const : Symbol(const) + } + [p2 satisfies keyof]() { +>[p2 satisfies keyof] : Symbol(Foo[p2 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 38, 13)) +>p2 : Symbol(p2, Decl(satisfiesKeyofGenerics.ts, 6, 10)) + + return 2 as const; +>const : Symbol(const) + } + [p3 satisfies keyof]() { +>[p3 satisfies keyof] : Symbol(Foo[p3 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 41, 13)) +>p3 : Symbol(p3, Decl(satisfiesKeyofGenerics.ts, 7, 19)) + + return 3 as const; +>const : Symbol(const) + } + [p4 satisfies keyof]() { +>[p4 satisfies keyof] : Symbol(Foo[p4 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 44, 13)) +>p4 : Symbol(p4, Decl(satisfiesKeyofGenerics.ts, 8, 16)) + + return 4 as const; +>const : Symbol(const) + } + [p5 satisfies keyof]() { +>[p5 satisfies keyof] : Symbol(Foo[p5 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 47, 13)) +>p5 : Symbol(p5, Decl(satisfiesKeyofGenerics.ts, 9, 19)) + + return 5 as const; +>const : Symbol(const) + } + [p6 satisfies keyof]() { +>[p6 satisfies keyof] : Symbol(Foo[p6 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 50, 13)) +>p6 : Symbol(p6, Decl(satisfiesKeyofGenerics.ts, 10, 16)) + + return 6 as const; +>const : Symbol(const) + } + [p7 satisfies keyof]() { +>[p7 satisfies keyof] : Symbol(Foo[p7 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 53, 13)) +>p7 : Symbol(p7, Decl(satisfiesKeyofGenerics.ts, 11, 24)) + + return 7 as const; +>const : Symbol(const) + } + [p8 satisfies keyof]() { +>[p8 satisfies keyof] : Symbol(Foo[p8 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 56, 13)) +>p8 : Symbol(p8, Decl(satisfiesKeyofGenerics.ts, 13, 10)) + + return 8 as const; +>const : Symbol(const) + } + [p9 satisfies keyof]() { +>[p9 satisfies keyof] : Symbol(Foo[p9 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 59, 13)) +>p9 : Symbol(p9, Decl(satisfiesKeyofGenerics.ts, 14, 19)) + + return 9 as const; +>const : Symbol(const) + } + [p10 satisfies keyof]() { +>[p10 satisfies keyof] : Symbol(Foo[p10 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 62, 13)) +>p10 : Symbol(p10, Decl(satisfiesKeyofGenerics.ts, 15, 16)) + + return 10 as const; +>const : Symbol(const) + } + [p11 satisfies keyof]() { +>[p11 satisfies keyof] : Symbol(Foo[p11 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 65, 13)) +>p11 : Symbol(p11, Decl(satisfiesKeyofGenerics.ts, 16, 20)) + + return 11 as const; +>const : Symbol(const) + } + [p12 satisfies keyof]() { +>[p12 satisfies keyof] : Symbol(Foo[p12 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 68, 13)) +>p12 : Symbol(p12, Decl(satisfiesKeyofGenerics.ts, 17, 17)) + + return 12 as const; +>const : Symbol(const) + } + [p13 satisfies keyof]() { +>[p13 satisfies keyof] : Symbol(Foo[p13 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 71, 13)) +>p13 : Symbol(p13, Decl(satisfiesKeyofGenerics.ts, 18, 25)) + + return 13 as const; +>const : Symbol(const) + } + [p14 satisfies keyof]() { +>[p14 satisfies keyof] : Symbol(Foo[p14 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 74, 13)) +>p14 : Symbol(p14, Decl(satisfiesKeyofGenerics.ts, 20, 11)) + + return 14 as const; +>const : Symbol(const) + } + [p15 satisfies keyof]() { +>[p15 satisfies keyof] : Symbol(Foo[p15 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 77, 13)) +>p15 : Symbol(p15, Decl(satisfiesKeyofGenerics.ts, 21, 20)) + + return 15 as const; +>const : Symbol(const) + } + [p16 satisfies keyof]() { +>[p16 satisfies keyof] : Symbol(Foo[p16 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 80, 13)) +>p16 : Symbol(p16, Decl(satisfiesKeyofGenerics.ts, 22, 24)) + + return 16 as const; +>const : Symbol(const) + } + [p17 satisfies keyof]() { +>[p17 satisfies keyof] : Symbol(Foo[p17 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 83, 13)) +>p17 : Symbol(p17, Decl(satisfiesKeyofGenerics.ts, 23, 20)) + + return 17 as const; +>const : Symbol(const) + } + [p18 satisfies keyof]() { +>[p18 satisfies keyof] : Symbol(Foo[p18 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 86, 13)) +>p18 : Symbol(p18, Decl(satisfiesKeyofGenerics.ts, 24, 24)) + + return 18 as const; +>const : Symbol(const) + } + [p19 satisfies keyof]() { +>[p19 satisfies keyof] : Symbol(Foo[p19 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 89, 13)) +>p19 : Symbol(p19, Decl(satisfiesKeyofGenerics.ts, 25, 32)) + + return 19 as const; +>const : Symbol(const) + } + [p20 satisfies keyof]() { +>[p20 satisfies keyof] : Symbol(Foo[p20 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 92, 13)) +>p20 : Symbol(p20, Decl(satisfiesKeyofGenerics.ts, 27, 11)) + + return 20 as const; +>const : Symbol(const) + } + [p21 satisfies keyof]() { +>[p21 satisfies keyof] : Symbol(Foo[p21 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 95, 13)) +>p21 : Symbol(p21, Decl(satisfiesKeyofGenerics.ts, 28, 20)) + + return 21 as const; +>const : Symbol(const) + } + [p22 satisfies keyof]() { +>[p22 satisfies keyof] : Symbol(Foo[p22 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 98, 13)) +>p22 : Symbol(p22, Decl(satisfiesKeyofGenerics.ts, 29, 22)) + + return 22 as const; +>const : Symbol(const) + } + [p23 satisfies keyof]() { +>[p23 satisfies keyof] : Symbol(Foo[p23 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 101, 13)) +>p23 : Symbol(p23, Decl(satisfiesKeyofGenerics.ts, 30, 20)) + + return 23 as const; +>const : Symbol(const) + } + [p24 satisfies keyof]() { +>[p24 satisfies keyof] : Symbol(Foo[p24 satisfies keyof], Decl(satisfiesKeyofGenerics.ts, 104, 13)) +>p24 : Symbol(p24, Decl(satisfiesKeyofGenerics.ts, 31, 22)) + + return 24 as const; +>const : Symbol(const) + } + } + ] as const; +>const : Symbol(const) +} diff --git a/tests/baselines/reference/satisfiesKeyofGenerics.types b/tests/baselines/reference/satisfiesKeyofGenerics.types new file mode 100644 index 0000000000000..208151ab29a93 --- /dev/null +++ b/tests/baselines/reference/satisfiesKeyofGenerics.types @@ -0,0 +1,460 @@ +//// [tests/cases/conformance/types/keyof/satisfiesKeyofGenerics.ts] //// + +=== satisfiesKeyofGenerics.ts === +export function f< +>f : (p1: T, p2: T & string, p3: T & "f", p4: T | string, p5: T | "g", p6: Extract, p7: U, p8: U & string, p9: U & "f", p10: U | string, p11: U | "g", p12: Extract, p13: V, p14: V & string, p15: V & "onefield", p16: V | string, p17: V | "onefield", p18: Extract, p19: W, p20: W & string, p21: W & "afield", p22: W | string, p23: W | "afield", p24: Extract) => readonly [typeof Foo] +> : ^ ^^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + T, + U extends string, + V extends "onefield", + W extends "afield" | "bfield", +>( + p1: T, +>p1 : T +> : ^ + + p2: T & string, +>p2 : T & string +> : ^^^^^^^^^^ + + p3: T & "f", +>p3 : T & "f" +> : ^^^^^^^ + + p4: T | string, +>p4 : string | T +> : ^^^^^^^^^^ + + p5: T | "g", +>p5 : T | "g" +> : ^^^^^^^ + + p6: Extract, +>p6 : Extract +> : ^^^^^^^^^^^^^^^ + + p7: U, +>p7 : U +> : ^ + + p8: U & string, +>p8 : U +> : ^ + + p9: U & "f", +>p9 : U & "f" +> : ^^^^^^^ + + p10: U | string, +>p10 : string | U +> : ^^^^^^^^^^ + + p11: U | "g", +>p11 : U | "g" +> : ^^^^^^^ + + p12: Extract, +>p12 : Extract +> : ^^^^^^^^^^^^^^^ + + p13: V, +>p13 : V +> : ^ + + p14: V & string, +>p14 : V +> : ^ + + p15: V & "onefield", +>p15 : V +> : ^ + + p16: V | string, +>p16 : string | V +> : ^^^^^^^^^^ + + p17: V | "onefield", +>p17 : V | "onefield" +> : ^^^^^^^^^^^^^^ + + p18: Extract, +>p18 : Extract +> : ^^^^^^^^^^^^^^^^^^^^^^ + + p19: W, +>p19 : W +> : ^ + + p20: W & string, +>p20 : W +> : ^ + + p21: W & "afield", // reduction rules for generics extending unions will simplify this to just "afield" where possible, so should be the only one that works without error +>p21 : W & "afield" +> : ^^^^^^^^^^^^ + + p22: W | string, +>p22 : string | W +> : ^^^^^^^^^^ + + p23: W | "afield", +>p23 : "afield" | W +> : ^^^^^^^^^^^^ + + p24: Extract, +>p24 : Extract +> : ^^^^^^^^^^^^^^^^^^^^ + +) { + return [ +>[ class Foo { [p1 satisfies keyof]() { return 1 as const; } [p2 satisfies keyof]() { return 2 as const; } [p3 satisfies keyof]() { return 3 as const; } [p4 satisfies keyof]() { return 4 as const; } [p5 satisfies keyof]() { return 5 as const; } [p6 satisfies keyof]() { return 6 as const; } [p7 satisfies keyof]() { return 7 as const; } [p8 satisfies keyof]() { return 8 as const; } [p9 satisfies keyof]() { return 9 as const; } [p10 satisfies keyof]() { return 10 as const; } [p11 satisfies keyof]() { return 11 as const; } [p12 satisfies keyof]() { return 12 as const; } [p13 satisfies keyof]() { return 13 as const; } [p14 satisfies keyof]() { return 14 as const; } [p15 satisfies keyof]() { return 15 as const; } [p16 satisfies keyof]() { return 16 as const; } [p17 satisfies keyof]() { return 17 as const; } [p18 satisfies keyof]() { return 18 as const; } [p19 satisfies keyof]() { return 19 as const; } [p20 satisfies keyof]() { return 20 as const; } [p21 satisfies keyof]() { return 21 as const; } [p22 satisfies keyof]() { return 22 as const; } [p23 satisfies keyof]() { return 23 as const; } [p24 satisfies keyof]() { return 24 as const; } } ] as const : readonly [typeof Foo] +> : ^^^^^^^^^^^^^^^^^^^^^ +>[ class Foo { [p1 satisfies keyof]() { return 1 as const; } [p2 satisfies keyof]() { return 2 as const; } [p3 satisfies keyof]() { return 3 as const; } [p4 satisfies keyof]() { return 4 as const; } [p5 satisfies keyof]() { return 5 as const; } [p6 satisfies keyof]() { return 6 as const; } [p7 satisfies keyof]() { return 7 as const; } [p8 satisfies keyof]() { return 8 as const; } [p9 satisfies keyof]() { return 9 as const; } [p10 satisfies keyof]() { return 10 as const; } [p11 satisfies keyof]() { return 11 as const; } [p12 satisfies keyof]() { return 12 as const; } [p13 satisfies keyof]() { return 13 as const; } [p14 satisfies keyof]() { return 14 as const; } [p15 satisfies keyof]() { return 15 as const; } [p16 satisfies keyof]() { return 16 as const; } [p17 satisfies keyof]() { return 17 as const; } [p18 satisfies keyof]() { return 18 as const; } [p19 satisfies keyof]() { return 19 as const; } [p20 satisfies keyof]() { return 20 as const; } [p21 satisfies keyof]() { return 21 as const; } [p22 satisfies keyof]() { return 22 as const; } [p23 satisfies keyof]() { return 23 as const; } [p24 satisfies keyof]() { return 24 as const; } } ] : readonly [typeof Foo] +> : ^^^^^^^^^^^^^^^^^^^^^ + + class Foo { +>class Foo { [p1 satisfies keyof]() { return 1 as const; } [p2 satisfies keyof]() { return 2 as const; } [p3 satisfies keyof]() { return 3 as const; } [p4 satisfies keyof]() { return 4 as const; } [p5 satisfies keyof]() { return 5 as const; } [p6 satisfies keyof]() { return 6 as const; } [p7 satisfies keyof]() { return 7 as const; } [p8 satisfies keyof]() { return 8 as const; } [p9 satisfies keyof]() { return 9 as const; } [p10 satisfies keyof]() { return 10 as const; } [p11 satisfies keyof]() { return 11 as const; } [p12 satisfies keyof]() { return 12 as const; } [p13 satisfies keyof]() { return 13 as const; } [p14 satisfies keyof]() { return 14 as const; } [p15 satisfies keyof]() { return 15 as const; } [p16 satisfies keyof]() { return 16 as const; } [p17 satisfies keyof]() { return 17 as const; } [p18 satisfies keyof]() { return 18 as const; } [p19 satisfies keyof]() { return 19 as const; } [p20 satisfies keyof]() { return 20 as const; } [p21 satisfies keyof]() { return 21 as const; } [p22 satisfies keyof]() { return 22 as const; } [p23 satisfies keyof]() { return 23 as const; } [p24 satisfies keyof]() { return 24 as const; } } : typeof Foo +> : ^^^^^^^^^^ +>Foo : typeof Foo +> : ^^^^^^^^^^ + + [p1 satisfies keyof]() { +>[p1 satisfies keyof] : () => 1 +> : ^^^^^^^ +>p1 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p1 : T +> : ^ + + return 1 as const; +>1 as const : 1 +> : ^ +>1 : 1 +> : ^ + } + [p2 satisfies keyof]() { +>[p2 satisfies keyof] : () => 2 +> : ^^^^^^^ +>p2 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p2 : T & string +> : ^^^^^^^^^^ + + return 2 as const; +>2 as const : 2 +> : ^ +>2 : 2 +> : ^ + } + [p3 satisfies keyof]() { +>[p3 satisfies keyof] : () => 3 +> : ^^^^^^^ +>p3 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p3 : T & "f" +> : ^^^^^^^ + + return 3 as const; +>3 as const : 3 +> : ^ +>3 : 3 +> : ^ + } + [p4 satisfies keyof]() { +>[p4 satisfies keyof] : () => 4 +> : ^^^^^^^ +>p4 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p4 : string | T +> : ^^^^^^^^^^ + + return 4 as const; +>4 as const : 4 +> : ^ +>4 : 4 +> : ^ + } + [p5 satisfies keyof]() { +>[p5 satisfies keyof] : () => 5 +> : ^^^^^^^ +>p5 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p5 : T | "g" +> : ^^^^^^^ + + return 5 as const; +>5 as const : 5 +> : ^ +>5 : 5 +> : ^ + } + [p6 satisfies keyof]() { +>[p6 satisfies keyof] : () => 6 +> : ^^^^^^^ +>p6 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p6 : Extract +> : ^^^^^^^^^^^^^^^ + + return 6 as const; +>6 as const : 6 +> : ^ +>6 : 6 +> : ^ + } + [p7 satisfies keyof]() { +>[p7 satisfies keyof] : () => 7 +> : ^^^^^^^ +>p7 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p7 : U +> : ^ + + return 7 as const; +>7 as const : 7 +> : ^ +>7 : 7 +> : ^ + } + [p8 satisfies keyof]() { +>[p8 satisfies keyof] : () => 8 +> : ^^^^^^^ +>p8 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p8 : U +> : ^ + + return 8 as const; +>8 as const : 8 +> : ^ +>8 : 8 +> : ^ + } + [p9 satisfies keyof]() { +>[p9 satisfies keyof] : () => 9 +> : ^^^^^^^ +>p9 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p9 : U & "f" +> : ^^^^^^^ + + return 9 as const; +>9 as const : 9 +> : ^ +>9 : 9 +> : ^ + } + [p10 satisfies keyof]() { +>[p10 satisfies keyof] : () => 10 +> : ^^^^^^^^ +>p10 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p10 : string | U +> : ^^^^^^^^^^ + + return 10 as const; +>10 as const : 10 +> : ^^ +>10 : 10 +> : ^^ + } + [p11 satisfies keyof]() { +>[p11 satisfies keyof] : () => 11 +> : ^^^^^^^^ +>p11 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p11 : U | "g" +> : ^^^^^^^ + + return 11 as const; +>11 as const : 11 +> : ^^ +>11 : 11 +> : ^^ + } + [p12 satisfies keyof]() { +>[p12 satisfies keyof] : () => 12 +> : ^^^^^^^^ +>p12 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p12 : Extract +> : ^^^^^^^^^^^^^^^ + + return 12 as const; +>12 as const : 12 +> : ^^ +>12 : 12 +> : ^^ + } + [p13 satisfies keyof]() { +>[p13 satisfies keyof] : () => 13 +> : ^^^^^^^^ +>p13 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p13 : V +> : ^ + + return 13 as const; +>13 as const : 13 +> : ^^ +>13 : 13 +> : ^^ + } + [p14 satisfies keyof]() { +>[p14 satisfies keyof] : () => 14 +> : ^^^^^^^^ +>p14 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p14 : V +> : ^ + + return 14 as const; +>14 as const : 14 +> : ^^ +>14 : 14 +> : ^^ + } + [p15 satisfies keyof]() { +>[p15 satisfies keyof] : () => 15 +> : ^^^^^^^^ +>p15 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p15 : V +> : ^ + + return 15 as const; +>15 as const : 15 +> : ^^ +>15 : 15 +> : ^^ + } + [p16 satisfies keyof]() { +>[p16 satisfies keyof] : () => 16 +> : ^^^^^^^^ +>p16 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p16 : string | V +> : ^^^^^^^^^^ + + return 16 as const; +>16 as const : 16 +> : ^^ +>16 : 16 +> : ^^ + } + [p17 satisfies keyof]() { +>[p17 satisfies keyof] : () => 17 +> : ^^^^^^^^ +>p17 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p17 : V | "onefield" +> : ^^^^^^^^^^^^^^ + + return 17 as const; +>17 as const : 17 +> : ^^ +>17 : 17 +> : ^^ + } + [p18 satisfies keyof]() { +>[p18 satisfies keyof] : () => 18 +> : ^^^^^^^^ +>p18 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p18 : Extract +> : ^^^^^^^^^^^^^^^^^^^^^^ + + return 18 as const; +>18 as const : 18 +> : ^^ +>18 : 18 +> : ^^ + } + [p19 satisfies keyof]() { +>[p19 satisfies keyof] : () => 19 +> : ^^^^^^^^ +>p19 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p19 : "afield" | "bfield" +> : ^^^^^^^^^^^^^^^^^^^ + + return 19 as const; +>19 as const : 19 +> : ^^ +>19 : 19 +> : ^^ + } + [p20 satisfies keyof]() { +>[p20 satisfies keyof] : () => 20 +> : ^^^^^^^^ +>p20 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p20 : "afield" | "bfield" +> : ^^^^^^^^^^^^^^^^^^^ + + return 20 as const; +>20 as const : 20 +> : ^^ +>20 : 20 +> : ^^ + } + [p21 satisfies keyof]() { +>[p21 satisfies keyof] : () => 21 +> : ^^^^^^^^ +>p21 satisfies keyof : "afield" +> : ^^^^^^^^ +>p21 : "afield" +> : ^^^^^^^^ + + return 21 as const; +>21 as const : 21 +> : ^^ +>21 : 21 +> : ^^ + } + [p22 satisfies keyof]() { +>[p22 satisfies keyof] : () => 22 +> : ^^^^^^^^ +>p22 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p22 : string +> : ^^^^^^ + + return 22 as const; +>22 as const : 22 +> : ^^ +>22 : 22 +> : ^^ + } + [p23 satisfies keyof]() { +>[p23 satisfies keyof] : () => 23 +> : ^^^^^^^^ +>p23 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p23 : "afield" | "bfield" +> : ^^^^^^^^^^^^^^^^^^^ + + return 23 as const; +>23 as const : 23 +> : ^^ +>23 : 23 +> : ^^ + } + [p24 satisfies keyof]() { +>[p24 satisfies keyof] : () => 24 +> : ^^^^^^^^ +>p24 satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>p24 : Extract +> : ^^^^^^^^^^^^^^^^^^^^ + + return 24 as const; +>24 as const : 24 +> : ^^ +>24 : 24 +> : ^^ + } + } + ] as const; +} diff --git a/tests/baselines/reference/satisfiesKeyofInputTypes.errors.txt b/tests/baselines/reference/satisfiesKeyofInputTypes.errors.txt new file mode 100644 index 0000000000000..614bc9ffab1cb --- /dev/null +++ b/tests/baselines/reference/satisfiesKeyofInputTypes.errors.txt @@ -0,0 +1,266 @@ +satisfiesKeyofInputTypes.ts(50,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(70,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(74,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(78,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(82,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(86,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(90,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(94,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(98,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(102,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(106,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(110,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(114,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(118,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(122,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(126,6): error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. +satisfiesKeyofInputTypes.ts(136,5): error TS7053: Element implicitly has an 'any' type because expression of type '"answer" | 42' can't be used to index type 'Foo'. + Property 'answer' does not exist on type 'Foo'. +satisfiesKeyofInputTypes.ts(141,5): error TS7053: Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'Foo'. +satisfiesKeyofInputTypes.ts(142,10): error TS2538: Type 'unknown' cannot be used as an index type. +satisfiesKeyofInputTypes.ts(143,5): error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Foo'. + No index signature with a parameter of type 'string' was found on type 'Foo'. +satisfiesKeyofInputTypes.ts(144,5): error TS7053: Element implicitly has an 'any' type because expression of type 'number' can't be used to index type 'Foo'. + No index signature with a parameter of type 'number' was found on type 'Foo'. +satisfiesKeyofInputTypes.ts(145,10): error TS2538: Type 'boolean' cannot be used as an index type. +satisfiesKeyofInputTypes.ts(146,10): error TS2538: Type 'true' cannot be used as an index type. +satisfiesKeyofInputTypes.ts(147,10): error TS2538: Type 'false' cannot be used as an index type. +satisfiesKeyofInputTypes.ts(148,10): error TS2538: Type 'null' cannot be used as an index type. +satisfiesKeyofInputTypes.ts(149,10): error TS2538: Type 'undefined' cannot be used as an index type. +satisfiesKeyofInputTypes.ts(150,10): error TS2538: Type 'bigint' cannot be used as an index type. +satisfiesKeyofInputTypes.ts(151,10): error TS2538: Type '22n' cannot be used as an index type. +satisfiesKeyofInputTypes.ts(152,5): error TS7053: Element implicitly has an 'any' type because expression of type 'symbol' can't be used to index type 'Foo'. +satisfiesKeyofInputTypes.ts(153,5): error TS2349: This expression is not callable. + Type 'never' has no call signatures. +satisfiesKeyofInputTypes.ts(154,5): error TS7053: Element implicitly has an 'any' type because expression of type '`aaa${string}`' can't be used to index type 'Foo'. +satisfiesKeyofInputTypes.ts(155,5): error TS7053: Element implicitly has an 'any' type because expression of type 'Lowercase' can't be used to index type 'Foo'. + + +==== satisfiesKeyofInputTypes.ts (32 errors) ==== + const sym = Symbol(); + const num = 1; + const str = "f"; + const union = Math.random() > 0.5 ? "answer" : 42; + + enum NumEnum { + A, + B, + } + + enum StrEnum { + A = "a", + B = "b" + } + + enum MixEnum { + A = 10, + B = "bb", + } + + const anything = null as any; + const unk = null as any as unknown; + const basestr = "" as string; + const basenum = 11 as number; + const bool = true as boolean; + const t = true; + const f = false; + const n = null; + const u = undefined; + const bigbase = 1n as bigint; + const biglit = 22n; + const symbase = null as any as symbol; + const nev = null as never; + const templateLit = `aaabb` as `aaa${string}`; + const mappingLit = `bbbaa` as Lowercase; + + export class Foo { + [sym satisfies keyof]() { + return 1 as const; + } + + [num satisfies keyof]() { + return 2 as const; + } + + [str satisfies keyof]() { + return 3 as const; + } + + [union satisfies keyof]() { + ~~~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 4 as const; + } + + [NumEnum.A satisfies keyof]() { + return 5 as const; + } + + [StrEnum.A satisfies keyof]() { + return 6 as const; + } + + [MixEnum.A satisfies keyof]() { + return 7 as const; + } + + [MixEnum.B satisfies keyof]() { + return 8 as const; + } + + [anything satisfies keyof]() { + ~~~~~~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 9 as const; + } + + [unk satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 10 as const; + } + + [basestr satisfies keyof]() { + ~~~~~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 11 as const; + } + + [basenum satisfies keyof]() { + ~~~~~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 12 as const; + } + + [bool satisfies keyof]() { + ~~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 13 as const; + } + + [t satisfies keyof]() { + ~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 14 as const; + } + + [f satisfies keyof]() { + ~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 15 as const; + } + + [n satisfies keyof]() { + ~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 16 as const; + } + + [u satisfies keyof]() { + ~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 17 as const; + } + + [bigbase satisfies keyof]() { + ~~~~~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 18 as const; + } + + [biglit satisfies keyof]() { + ~~~~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 19 as const; + } + + [symbase satisfies keyof]() { + ~~~~~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 20 as const; + } + + [nev satisfies keyof]() { + ~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 21 as const; + } + + [templateLit satisfies keyof]() { + ~~~~~~~~~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 22 as const; + } + + [mappingLit satisfies keyof]() { + ~~~~~~~~~~ +!!! error TS9041: A `satisfies keyof` computed property name must be exactly a single string, number, or unique symbol literal type. + return 23 as const; + } + } + + const inst = new Foo(); + export const results = [ + inst[sym](), + inst[num](), + inst[str](), + inst[union](), + ~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type '"answer" | 42' can't be used to index type 'Foo'. +!!! error TS7053: Property 'answer' does not exist on type 'Foo'. + inst[NumEnum.A](), + inst[StrEnum.A](), + inst[MixEnum.A](), + inst[MixEnum.B](), + inst[anything](), + ~~~~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'Foo'. + inst[unk](), + ~~~ +!!! error TS2538: Type 'unknown' cannot be used as an index type. + inst[basestr](), + ~~~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Foo'. +!!! error TS7053: No index signature with a parameter of type 'string' was found on type 'Foo'. + inst[basenum](), + ~~~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type 'number' can't be used to index type 'Foo'. +!!! error TS7053: No index signature with a parameter of type 'number' was found on type 'Foo'. + inst[bool](), + ~~~~ +!!! error TS2538: Type 'boolean' cannot be used as an index type. + inst[t](), + ~ +!!! error TS2538: Type 'true' cannot be used as an index type. + inst[f](), + ~ +!!! error TS2538: Type 'false' cannot be used as an index type. + inst[n](), + ~ +!!! error TS2538: Type 'null' cannot be used as an index type. + inst[u](), + ~ +!!! error TS2538: Type 'undefined' cannot be used as an index type. + inst[bigbase](), + ~~~~~~~ +!!! error TS2538: Type 'bigint' cannot be used as an index type. + inst[biglit](), + ~~~~~~ +!!! error TS2538: Type '22n' cannot be used as an index type. + inst[symbase](), + ~~~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type 'symbol' can't be used to index type 'Foo'. + inst[nev](), // indexing by `never` always gives `never`, rather than the fallback index property + ~~~~~~~~~ +!!! error TS2349: This expression is not callable. +!!! error TS2349: Type 'never' has no call signatures. + inst[templateLit](), + ~~~~~~~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type '`aaa${string}`' can't be used to index type 'Foo'. + inst[mappingLit](), + ~~~~~~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type 'Lowercase' can't be used to index type 'Foo'. + ] as const; + + + \ No newline at end of file diff --git a/tests/baselines/reference/satisfiesKeyofInputTypes.js b/tests/baselines/reference/satisfiesKeyofInputTypes.js new file mode 100644 index 0000000000000..66a40f575cee9 --- /dev/null +++ b/tests/baselines/reference/satisfiesKeyofInputTypes.js @@ -0,0 +1,356 @@ +//// [tests/cases/conformance/types/keyof/satisfiesKeyofInputTypes.ts] //// + +//// [satisfiesKeyofInputTypes.ts] +const sym = Symbol(); +const num = 1; +const str = "f"; +const union = Math.random() > 0.5 ? "answer" : 42; + +enum NumEnum { + A, + B, +} + +enum StrEnum { + A = "a", + B = "b" +} + +enum MixEnum { + A = 10, + B = "bb", +} + +const anything = null as any; +const unk = null as any as unknown; +const basestr = "" as string; +const basenum = 11 as number; +const bool = true as boolean; +const t = true; +const f = false; +const n = null; +const u = undefined; +const bigbase = 1n as bigint; +const biglit = 22n; +const symbase = null as any as symbol; +const nev = null as never; +const templateLit = `aaabb` as `aaa${string}`; +const mappingLit = `bbbaa` as Lowercase; + +export class Foo { + [sym satisfies keyof]() { + return 1 as const; + } + + [num satisfies keyof]() { + return 2 as const; + } + + [str satisfies keyof]() { + return 3 as const; + } + + [union satisfies keyof]() { + return 4 as const; + } + + [NumEnum.A satisfies keyof]() { + return 5 as const; + } + + [StrEnum.A satisfies keyof]() { + return 6 as const; + } + + [MixEnum.A satisfies keyof]() { + return 7 as const; + } + + [MixEnum.B satisfies keyof]() { + return 8 as const; + } + + [anything satisfies keyof]() { + return 9 as const; + } + + [unk satisfies keyof]() { + return 10 as const; + } + + [basestr satisfies keyof]() { + return 11 as const; + } + + [basenum satisfies keyof]() { + return 12 as const; + } + + [bool satisfies keyof]() { + return 13 as const; + } + + [t satisfies keyof]() { + return 14 as const; + } + + [f satisfies keyof]() { + return 15 as const; + } + + [n satisfies keyof]() { + return 16 as const; + } + + [u satisfies keyof]() { + return 17 as const; + } + + [bigbase satisfies keyof]() { + return 18 as const; + } + + [biglit satisfies keyof]() { + return 19 as const; + } + + [symbase satisfies keyof]() { + return 20 as const; + } + + [nev satisfies keyof]() { + return 21 as const; + } + + [templateLit satisfies keyof]() { + return 22 as const; + } + + [mappingLit satisfies keyof]() { + return 23 as const; + } +} + +const inst = new Foo(); +export const results = [ + inst[sym](), + inst[num](), + inst[str](), + inst[union](), + inst[NumEnum.A](), + inst[StrEnum.A](), + inst[MixEnum.A](), + inst[MixEnum.B](), + inst[anything](), + inst[unk](), + inst[basestr](), + inst[basenum](), + inst[bool](), + inst[t](), + inst[f](), + inst[n](), + inst[u](), + inst[bigbase](), + inst[biglit](), + inst[symbase](), + inst[nev](), // indexing by `never` always gives `never`, rather than the fallback index property + inst[templateLit](), + inst[mappingLit](), +] as const; + + + + +//// [satisfiesKeyofInputTypes.js] +const sym = Symbol(); +const num = 1; +const str = "f"; +const union = Math.random() > 0.5 ? "answer" : 42; +var NumEnum; +(function (NumEnum) { + NumEnum[NumEnum["A"] = 0] = "A"; + NumEnum[NumEnum["B"] = 1] = "B"; +})(NumEnum || (NumEnum = {})); +var StrEnum; +(function (StrEnum) { + StrEnum["A"] = "a"; + StrEnum["B"] = "b"; +})(StrEnum || (StrEnum = {})); +var MixEnum; +(function (MixEnum) { + MixEnum[MixEnum["A"] = 10] = "A"; + MixEnum["B"] = "bb"; +})(MixEnum || (MixEnum = {})); +const anything = null; +const unk = null; +const basestr = ""; +const basenum = 11; +const bool = true; +const t = true; +const f = false; +const n = null; +const u = undefined; +const bigbase = 1n; +const biglit = 22n; +const symbase = null; +const nev = null; +const templateLit = `aaabb`; +const mappingLit = `bbbaa`; +export class Foo { + [sym]() { + return 1; + } + [num]() { + return 2; + } + [str]() { + return 3; + } + [union]() { + return 4; + } + [NumEnum.A]() { + return 5; + } + [StrEnum.A]() { + return 6; + } + [MixEnum.A]() { + return 7; + } + [MixEnum.B]() { + return 8; + } + [anything]() { + return 9; + } + [unk]() { + return 10; + } + [basestr]() { + return 11; + } + [basenum]() { + return 12; + } + [bool]() { + return 13; + } + [t]() { + return 14; + } + [f]() { + return 15; + } + [n]() { + return 16; + } + [u]() { + return 17; + } + [bigbase]() { + return 18; + } + [biglit]() { + return 19; + } + [symbase]() { + return 20; + } + [nev]() { + return 21; + } + [templateLit]() { + return 22; + } + [mappingLit]() { + return 23; + } +} +const inst = new Foo(); +export const results = [ + inst[sym](), + inst[num](), + inst[str](), + inst[union](), + inst[NumEnum.A](), + inst[StrEnum.A](), + inst[MixEnum.A](), + inst[MixEnum.B](), + inst[anything](), + inst[unk](), + inst[basestr](), + inst[basenum](), + inst[bool](), + inst[t](), + inst[f](), + inst[n](), + inst[u](), + inst[bigbase](), + inst[biglit](), + inst[symbase](), + inst[nev](), // indexing by `never` always gives `never`, rather than the fallback index property + inst[templateLit](), + inst[mappingLit](), +]; + + +//// [satisfiesKeyofInputTypes.d.ts] +declare const sym: unique symbol; +declare const num = 1; +declare const str = "f"; +declare const union: string | number; +declare enum NumEnum { + A = 0, + B = 1 +} +declare enum StrEnum { + A = "a", + B = "b" +} +declare enum MixEnum { + A = 10, + B = "bb" +} +declare const anything: any; +declare const unk: unknown; +declare const basestr: string; +declare const basenum: number; +declare const bool: boolean; +declare const t = true; +declare const f = false; +declare const n: null; +declare const u: undefined; +declare const bigbase: bigint; +declare const biglit = 22n; +declare const symbase: symbol; +declare const nev: never; +declare const templateLit: `aaa${string}`; +declare const mappingLit: Lowercase; +export declare class Foo { + [sym](): 1; + [num](): 2; + [str](): 3; + [union](): 4; + [NumEnum.A](): 5; + [StrEnum.A](): 6; + [MixEnum.A](): 7; + [MixEnum.B](): 8; + [anything](): 9; + [unk](): 10; + [basestr](): 11; + [basenum](): 12; + [bool](): 13; + [t](): 14; + [f](): 15; + [n](): 16; + [u](): 17; + [bigbase](): 18; + [biglit](): 19; + [symbase](): 20; + [nev](): 21; + [templateLit](): 22; + [mappingLit](): 23; +} +export declare const results: readonly [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, any, 22, 23]; +export {}; diff --git a/tests/baselines/reference/satisfiesKeyofInputTypes.symbols b/tests/baselines/reference/satisfiesKeyofInputTypes.symbols new file mode 100644 index 0000000000000..c37d7fde73ea3 --- /dev/null +++ b/tests/baselines/reference/satisfiesKeyofInputTypes.symbols @@ -0,0 +1,404 @@ +//// [tests/cases/conformance/types/keyof/satisfiesKeyofInputTypes.ts] //// + +=== satisfiesKeyofInputTypes.ts === +const sym = Symbol(); +>sym : Symbol(sym, Decl(satisfiesKeyofInputTypes.ts, 0, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) + +const num = 1; +>num : Symbol(num, Decl(satisfiesKeyofInputTypes.ts, 1, 5)) + +const str = "f"; +>str : Symbol(str, Decl(satisfiesKeyofInputTypes.ts, 2, 5)) + +const union = Math.random() > 0.5 ? "answer" : 42; +>union : Symbol(union, Decl(satisfiesKeyofInputTypes.ts, 3, 5)) +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + +enum NumEnum { +>NumEnum : Symbol(NumEnum, Decl(satisfiesKeyofInputTypes.ts, 3, 50)) + + A, +>A : Symbol(NumEnum.A, Decl(satisfiesKeyofInputTypes.ts, 5, 14)) + + B, +>B : Symbol(NumEnum.B, Decl(satisfiesKeyofInputTypes.ts, 6, 6)) +} + +enum StrEnum { +>StrEnum : Symbol(StrEnum, Decl(satisfiesKeyofInputTypes.ts, 8, 1)) + + A = "a", +>A : Symbol(StrEnum.A, Decl(satisfiesKeyofInputTypes.ts, 10, 14)) + + B = "b" +>B : Symbol(StrEnum.B, Decl(satisfiesKeyofInputTypes.ts, 11, 12)) +} + +enum MixEnum { +>MixEnum : Symbol(MixEnum, Decl(satisfiesKeyofInputTypes.ts, 13, 1)) + + A = 10, +>A : Symbol(MixEnum.A, Decl(satisfiesKeyofInputTypes.ts, 15, 14)) + + B = "bb", +>B : Symbol(MixEnum.B, Decl(satisfiesKeyofInputTypes.ts, 16, 11)) +} + +const anything = null as any; +>anything : Symbol(anything, Decl(satisfiesKeyofInputTypes.ts, 20, 5)) + +const unk = null as any as unknown; +>unk : Symbol(unk, Decl(satisfiesKeyofInputTypes.ts, 21, 5)) + +const basestr = "" as string; +>basestr : Symbol(basestr, Decl(satisfiesKeyofInputTypes.ts, 22, 5)) + +const basenum = 11 as number; +>basenum : Symbol(basenum, Decl(satisfiesKeyofInputTypes.ts, 23, 5)) + +const bool = true as boolean; +>bool : Symbol(bool, Decl(satisfiesKeyofInputTypes.ts, 24, 5)) + +const t = true; +>t : Symbol(t, Decl(satisfiesKeyofInputTypes.ts, 25, 5)) + +const f = false; +>f : Symbol(f, Decl(satisfiesKeyofInputTypes.ts, 26, 5)) + +const n = null; +>n : Symbol(n, Decl(satisfiesKeyofInputTypes.ts, 27, 5)) + +const u = undefined; +>u : Symbol(u, Decl(satisfiesKeyofInputTypes.ts, 28, 5)) +>undefined : Symbol(undefined) + +const bigbase = 1n as bigint; +>bigbase : Symbol(bigbase, Decl(satisfiesKeyofInputTypes.ts, 29, 5)) + +const biglit = 22n; +>biglit : Symbol(biglit, Decl(satisfiesKeyofInputTypes.ts, 30, 5)) + +const symbase = null as any as symbol; +>symbase : Symbol(symbase, Decl(satisfiesKeyofInputTypes.ts, 31, 5)) + +const nev = null as never; +>nev : Symbol(nev, Decl(satisfiesKeyofInputTypes.ts, 32, 5)) + +const templateLit = `aaabb` as `aaa${string}`; +>templateLit : Symbol(templateLit, Decl(satisfiesKeyofInputTypes.ts, 33, 5)) + +const mappingLit = `bbbaa` as Lowercase; +>mappingLit : Symbol(mappingLit, Decl(satisfiesKeyofInputTypes.ts, 34, 5)) +>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --)) + +export class Foo { +>Foo : Symbol(Foo, Decl(satisfiesKeyofInputTypes.ts, 34, 48)) + + [sym satisfies keyof]() { +>[sym satisfies keyof] : Symbol(Foo[sym satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 36, 18)) +>sym : Symbol(sym, Decl(satisfiesKeyofInputTypes.ts, 0, 5)) + + return 1 as const; +>const : Symbol(const) + } + + [num satisfies keyof]() { +>[num satisfies keyof] : Symbol(Foo[num satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 39, 5)) +>num : Symbol(num, Decl(satisfiesKeyofInputTypes.ts, 1, 5)) + + return 2 as const; +>const : Symbol(const) + } + + [str satisfies keyof]() { +>[str satisfies keyof] : Symbol(Foo[str satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 43, 5)) +>str : Symbol(str, Decl(satisfiesKeyofInputTypes.ts, 2, 5)) + + return 3 as const; +>const : Symbol(const) + } + + [union satisfies keyof]() { +>[union satisfies keyof] : Symbol(Foo[union satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 47, 5)) +>union : Symbol(union, Decl(satisfiesKeyofInputTypes.ts, 3, 5)) + + return 4 as const; +>const : Symbol(const) + } + + [NumEnum.A satisfies keyof]() { +>[NumEnum.A satisfies keyof] : Symbol(Foo[NumEnum.A satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 51, 5)) +>NumEnum.A : Symbol(NumEnum.A, Decl(satisfiesKeyofInputTypes.ts, 5, 14)) +>NumEnum : Symbol(NumEnum, Decl(satisfiesKeyofInputTypes.ts, 3, 50)) +>A : Symbol(NumEnum.A, Decl(satisfiesKeyofInputTypes.ts, 5, 14)) + + return 5 as const; +>const : Symbol(const) + } + + [StrEnum.A satisfies keyof]() { +>[StrEnum.A satisfies keyof] : Symbol(Foo[StrEnum.A satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 55, 5)) +>StrEnum.A : Symbol(StrEnum.A, Decl(satisfiesKeyofInputTypes.ts, 10, 14)) +>StrEnum : Symbol(StrEnum, Decl(satisfiesKeyofInputTypes.ts, 8, 1)) +>A : Symbol(StrEnum.A, Decl(satisfiesKeyofInputTypes.ts, 10, 14)) + + return 6 as const; +>const : Symbol(const) + } + + [MixEnum.A satisfies keyof]() { +>[MixEnum.A satisfies keyof] : Symbol(Foo[MixEnum.A satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 59, 5)) +>MixEnum.A : Symbol(MixEnum.A, Decl(satisfiesKeyofInputTypes.ts, 15, 14)) +>MixEnum : Symbol(MixEnum, Decl(satisfiesKeyofInputTypes.ts, 13, 1)) +>A : Symbol(MixEnum.A, Decl(satisfiesKeyofInputTypes.ts, 15, 14)) + + return 7 as const; +>const : Symbol(const) + } + + [MixEnum.B satisfies keyof]() { +>[MixEnum.B satisfies keyof] : Symbol(Foo[MixEnum.B satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 63, 5)) +>MixEnum.B : Symbol(MixEnum.B, Decl(satisfiesKeyofInputTypes.ts, 16, 11)) +>MixEnum : Symbol(MixEnum, Decl(satisfiesKeyofInputTypes.ts, 13, 1)) +>B : Symbol(MixEnum.B, Decl(satisfiesKeyofInputTypes.ts, 16, 11)) + + return 8 as const; +>const : Symbol(const) + } + + [anything satisfies keyof]() { +>[anything satisfies keyof] : Symbol(Foo[anything satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 67, 5)) +>anything : Symbol(anything, Decl(satisfiesKeyofInputTypes.ts, 20, 5)) + + return 9 as const; +>const : Symbol(const) + } + + [unk satisfies keyof]() { +>[unk satisfies keyof] : Symbol(Foo[unk satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 71, 5)) +>unk : Symbol(unk, Decl(satisfiesKeyofInputTypes.ts, 21, 5)) + + return 10 as const; +>const : Symbol(const) + } + + [basestr satisfies keyof]() { +>[basestr satisfies keyof] : Symbol(Foo[basestr satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 75, 5)) +>basestr : Symbol(basestr, Decl(satisfiesKeyofInputTypes.ts, 22, 5)) + + return 11 as const; +>const : Symbol(const) + } + + [basenum satisfies keyof]() { +>[basenum satisfies keyof] : Symbol(Foo[basenum satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 79, 5)) +>basenum : Symbol(basenum, Decl(satisfiesKeyofInputTypes.ts, 23, 5)) + + return 12 as const; +>const : Symbol(const) + } + + [bool satisfies keyof]() { +>[bool satisfies keyof] : Symbol(Foo[bool satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 83, 5)) +>bool : Symbol(bool, Decl(satisfiesKeyofInputTypes.ts, 24, 5)) + + return 13 as const; +>const : Symbol(const) + } + + [t satisfies keyof]() { +>[t satisfies keyof] : Symbol(Foo[t satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 87, 5)) +>t : Symbol(t, Decl(satisfiesKeyofInputTypes.ts, 25, 5)) + + return 14 as const; +>const : Symbol(const) + } + + [f satisfies keyof]() { +>[f satisfies keyof] : Symbol(Foo[f satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 91, 5)) +>f : Symbol(f, Decl(satisfiesKeyofInputTypes.ts, 26, 5)) + + return 15 as const; +>const : Symbol(const) + } + + [n satisfies keyof]() { +>[n satisfies keyof] : Symbol(Foo[n satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 95, 5)) +>n : Symbol(n, Decl(satisfiesKeyofInputTypes.ts, 27, 5)) + + return 16 as const; +>const : Symbol(const) + } + + [u satisfies keyof]() { +>[u satisfies keyof] : Symbol(Foo[u satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 99, 5)) +>u : Symbol(u, Decl(satisfiesKeyofInputTypes.ts, 28, 5)) + + return 17 as const; +>const : Symbol(const) + } + + [bigbase satisfies keyof]() { +>[bigbase satisfies keyof] : Symbol(Foo[bigbase satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 103, 5)) +>bigbase : Symbol(bigbase, Decl(satisfiesKeyofInputTypes.ts, 29, 5)) + + return 18 as const; +>const : Symbol(const) + } + + [biglit satisfies keyof]() { +>[biglit satisfies keyof] : Symbol(Foo[biglit satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 107, 5)) +>biglit : Symbol(biglit, Decl(satisfiesKeyofInputTypes.ts, 30, 5)) + + return 19 as const; +>const : Symbol(const) + } + + [symbase satisfies keyof]() { +>[symbase satisfies keyof] : Symbol(Foo[symbase satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 111, 5)) +>symbase : Symbol(symbase, Decl(satisfiesKeyofInputTypes.ts, 31, 5)) + + return 20 as const; +>const : Symbol(const) + } + + [nev satisfies keyof]() { +>[nev satisfies keyof] : Symbol(Foo[nev satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 115, 5)) +>nev : Symbol(nev, Decl(satisfiesKeyofInputTypes.ts, 32, 5)) + + return 21 as const; +>const : Symbol(const) + } + + [templateLit satisfies keyof]() { +>[templateLit satisfies keyof] : Symbol(Foo[templateLit satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 119, 5)) +>templateLit : Symbol(templateLit, Decl(satisfiesKeyofInputTypes.ts, 33, 5)) + + return 22 as const; +>const : Symbol(const) + } + + [mappingLit satisfies keyof]() { +>[mappingLit satisfies keyof] : Symbol(Foo[mappingLit satisfies keyof], Decl(satisfiesKeyofInputTypes.ts, 123, 5)) +>mappingLit : Symbol(mappingLit, Decl(satisfiesKeyofInputTypes.ts, 34, 5)) + + return 23 as const; +>const : Symbol(const) + } +} + +const inst = new Foo(); +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>Foo : Symbol(Foo, Decl(satisfiesKeyofInputTypes.ts, 34, 48)) + +export const results = [ +>results : Symbol(results, Decl(satisfiesKeyofInputTypes.ts, 131, 12)) + + inst[sym](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>sym : Symbol(sym, Decl(satisfiesKeyofInputTypes.ts, 0, 5)) + + inst[num](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>num : Symbol(num, Decl(satisfiesKeyofInputTypes.ts, 1, 5)) + + inst[str](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>str : Symbol(str, Decl(satisfiesKeyofInputTypes.ts, 2, 5)) + + inst[union](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>union : Symbol(union, Decl(satisfiesKeyofInputTypes.ts, 3, 5)) + + inst[NumEnum.A](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>NumEnum.A : Symbol(NumEnum.A, Decl(satisfiesKeyofInputTypes.ts, 5, 14)) +>NumEnum : Symbol(NumEnum, Decl(satisfiesKeyofInputTypes.ts, 3, 50)) +>A : Symbol(NumEnum.A, Decl(satisfiesKeyofInputTypes.ts, 5, 14)) + + inst[StrEnum.A](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>StrEnum.A : Symbol(StrEnum.A, Decl(satisfiesKeyofInputTypes.ts, 10, 14)) +>StrEnum : Symbol(StrEnum, Decl(satisfiesKeyofInputTypes.ts, 8, 1)) +>A : Symbol(StrEnum.A, Decl(satisfiesKeyofInputTypes.ts, 10, 14)) + + inst[MixEnum.A](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>MixEnum.A : Symbol(MixEnum.A, Decl(satisfiesKeyofInputTypes.ts, 15, 14)) +>MixEnum : Symbol(MixEnum, Decl(satisfiesKeyofInputTypes.ts, 13, 1)) +>A : Symbol(MixEnum.A, Decl(satisfiesKeyofInputTypes.ts, 15, 14)) + + inst[MixEnum.B](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>MixEnum.B : Symbol(MixEnum.B, Decl(satisfiesKeyofInputTypes.ts, 16, 11)) +>MixEnum : Symbol(MixEnum, Decl(satisfiesKeyofInputTypes.ts, 13, 1)) +>B : Symbol(MixEnum.B, Decl(satisfiesKeyofInputTypes.ts, 16, 11)) + + inst[anything](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>anything : Symbol(anything, Decl(satisfiesKeyofInputTypes.ts, 20, 5)) + + inst[unk](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>unk : Symbol(unk, Decl(satisfiesKeyofInputTypes.ts, 21, 5)) + + inst[basestr](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>basestr : Symbol(basestr, Decl(satisfiesKeyofInputTypes.ts, 22, 5)) + + inst[basenum](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>basenum : Symbol(basenum, Decl(satisfiesKeyofInputTypes.ts, 23, 5)) + + inst[bool](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>bool : Symbol(bool, Decl(satisfiesKeyofInputTypes.ts, 24, 5)) + + inst[t](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>t : Symbol(t, Decl(satisfiesKeyofInputTypes.ts, 25, 5)) + + inst[f](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>f : Symbol(f, Decl(satisfiesKeyofInputTypes.ts, 26, 5)) + + inst[n](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>n : Symbol(n, Decl(satisfiesKeyofInputTypes.ts, 27, 5)) + + inst[u](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>u : Symbol(u, Decl(satisfiesKeyofInputTypes.ts, 28, 5)) + + inst[bigbase](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>bigbase : Symbol(bigbase, Decl(satisfiesKeyofInputTypes.ts, 29, 5)) + + inst[biglit](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>biglit : Symbol(biglit, Decl(satisfiesKeyofInputTypes.ts, 30, 5)) + + inst[symbase](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>symbase : Symbol(symbase, Decl(satisfiesKeyofInputTypes.ts, 31, 5)) + + inst[nev](), // indexing by `never` always gives `never`, rather than the fallback index property +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>nev : Symbol(nev, Decl(satisfiesKeyofInputTypes.ts, 32, 5)) + + inst[templateLit](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>templateLit : Symbol(templateLit, Decl(satisfiesKeyofInputTypes.ts, 33, 5)) + + inst[mappingLit](), +>inst : Symbol(inst, Decl(satisfiesKeyofInputTypes.ts, 130, 5)) +>mappingLit : Symbol(mappingLit, Decl(satisfiesKeyofInputTypes.ts, 34, 5)) + +] as const; +>const : Symbol(const) + + + diff --git a/tests/baselines/reference/satisfiesKeyofInputTypes.types b/tests/baselines/reference/satisfiesKeyofInputTypes.types new file mode 100644 index 0000000000000..c164ed52837ed --- /dev/null +++ b/tests/baselines/reference/satisfiesKeyofInputTypes.types @@ -0,0 +1,828 @@ +//// [tests/cases/conformance/types/keyof/satisfiesKeyofInputTypes.ts] //// + +=== satisfiesKeyofInputTypes.ts === +const sym = Symbol(); +>sym : unique symbol +> : ^^^^^^^^^^^^^ +>Symbol() : unique symbol +> : ^^^^^^^^^^^^^ +>Symbol : SymbolConstructor +> : ^^^^^^^^^^^^^^^^^ + +const num = 1; +>num : 1 +> : ^ +>1 : 1 +> : ^ + +const str = "f"; +>str : "f" +> : ^^^ +>"f" : "f" +> : ^^^ + +const union = Math.random() > 0.5 ? "answer" : 42; +>union : "answer" | 42 +> : ^^^^^^^^^^^^^ +>Math.random() > 0.5 ? "answer" : 42 : "answer" | 42 +> : ^^^^^^^^^^^^^ +>Math.random() > 0.5 : boolean +> : ^^^^^^^ +>Math.random() : number +> : ^^^^^^ +>Math.random : () => number +> : ^^^^^^ +>Math : Math +> : ^^^^ +>random : () => number +> : ^^^^^^ +>0.5 : 0.5 +> : ^^^ +>"answer" : "answer" +> : ^^^^^^^^ +>42 : 42 +> : ^^ + +enum NumEnum { +>NumEnum : NumEnum +> : ^^^^^^^ + + A, +>A : NumEnum.A +> : ^^^^^^^^^ + + B, +>B : NumEnum.B +> : ^^^^^^^^^ +} + +enum StrEnum { +>StrEnum : StrEnum +> : ^^^^^^^ + + A = "a", +>A : StrEnum.A +> : ^^^^^^^^^ +>"a" : "a" +> : ^^^ + + B = "b" +>B : StrEnum.B +> : ^^^^^^^^^ +>"b" : "b" +> : ^^^ +} + +enum MixEnum { +>MixEnum : MixEnum +> : ^^^^^^^ + + A = 10, +>A : MixEnum.A +> : ^^^^^^^^^ +>10 : 10 +> : ^^ + + B = "bb", +>B : MixEnum.B +> : ^^^^^^^^^ +>"bb" : "bb" +> : ^^^^ +} + +const anything = null as any; +>anything : any +> : ^^^ +>null as any : any +> : ^^^ + +const unk = null as any as unknown; +>unk : unknown +> : ^^^^^^^ +>null as any as unknown : unknown +> : ^^^^^^^ +>null as any : any +> : ^^^ + +const basestr = "" as string; +>basestr : string +> : ^^^^^^ +>"" as string : string +> : ^^^^^^ +>"" : "" +> : ^^ + +const basenum = 11 as number; +>basenum : number +> : ^^^^^^ +>11 as number : number +> : ^^^^^^ +>11 : 11 +> : ^^ + +const bool = true as boolean; +>bool : boolean +> : ^^^^^^^ +>true as boolean : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ + +const t = true; +>t : true +> : ^^^^ +>true : true +> : ^^^^ + +const f = false; +>f : false +> : ^^^^^ +>false : false +> : ^^^^^ + +const n = null; +>n : null +> : ^^^^ + +const u = undefined; +>u : undefined +> : ^^^^^^^^^ +>undefined : undefined +> : ^^^^^^^^^ + +const bigbase = 1n as bigint; +>bigbase : bigint +> : ^^^^^^ +>1n as bigint : bigint +> : ^^^^^^ +>1n : 1n +> : ^^ + +const biglit = 22n; +>biglit : 22n +> : ^^^ +>22n : 22n +> : ^^^ + +const symbase = null as any as symbol; +>symbase : symbol +> : ^^^^^^ +>null as any as symbol : symbol +> : ^^^^^^ +>null as any : any +> : ^^^ + +const nev = null as never; +>nev : never +> : ^^^^^ +>null as never : never +> : ^^^^^ + +const templateLit = `aaabb` as `aaa${string}`; +>templateLit : `aaa${string}` +> : ^^^^^^^^^^^^^^ +>`aaabb` as `aaa${string}` : `aaa${string}` +> : ^^^^^^^^^^^^^^ +>`aaabb` : "aaabb" +> : ^^^^^^^ + +const mappingLit = `bbbaa` as Lowercase; +>mappingLit : Lowercase +> : ^^^^^^^^^^^^^^^^^ +>`bbbaa` as Lowercase : Lowercase +> : ^^^^^^^^^^^^^^^^^ +>`bbbaa` : "bbbaa" +> : ^^^^^^^ + +export class Foo { +>Foo : Foo +> : ^^^ + + [sym satisfies keyof]() { +>[sym satisfies keyof] : () => 1 +> : ^^^^^^^ +>sym satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>sym : unique symbol +> : ^^^^^^^^^^^^^ + + return 1 as const; +>1 as const : 1 +> : ^ +>1 : 1 +> : ^ + } + + [num satisfies keyof]() { +>[num satisfies keyof] : () => 2 +> : ^^^^^^^ +>num satisfies keyof : 1 +> : ^ +>num : 1 +> : ^ + + return 2 as const; +>2 as const : 2 +> : ^ +>2 : 2 +> : ^ + } + + [str satisfies keyof]() { +>[str satisfies keyof] : () => 3 +> : ^^^^^^^ +>str satisfies keyof : "f" +> : ^^^ +>str : "f" +> : ^^^ + + return 3 as const; +>3 as const : 3 +> : ^ +>3 : 3 +> : ^ + } + + [union satisfies keyof]() { +>[union satisfies keyof] : () => 4 +> : ^^^^^^^ +>union satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>union : "answer" | 42 +> : ^^^^^^^^^^^^^ + + return 4 as const; +>4 as const : 4 +> : ^ +>4 : 4 +> : ^ + } + + [NumEnum.A satisfies keyof]() { +>[NumEnum.A satisfies keyof] : () => 5 +> : ^^^^^^^ +>NumEnum.A satisfies keyof : NumEnum.A +> : ^^^^^^^^^ +>NumEnum.A : NumEnum.A +> : ^^^^^^^^^ +>NumEnum : typeof NumEnum +> : ^^^^^^^^^^^^^^ +>A : NumEnum.A +> : ^^^^^^^^^ + + return 5 as const; +>5 as const : 5 +> : ^ +>5 : 5 +> : ^ + } + + [StrEnum.A satisfies keyof]() { +>[StrEnum.A satisfies keyof] : () => 6 +> : ^^^^^^^ +>StrEnum.A satisfies keyof : StrEnum.A +> : ^^^^^^^^^ +>StrEnum.A : StrEnum.A +> : ^^^^^^^^^ +>StrEnum : typeof StrEnum +> : ^^^^^^^^^^^^^^ +>A : StrEnum.A +> : ^^^^^^^^^ + + return 6 as const; +>6 as const : 6 +> : ^ +>6 : 6 +> : ^ + } + + [MixEnum.A satisfies keyof]() { +>[MixEnum.A satisfies keyof] : () => 7 +> : ^^^^^^^ +>MixEnum.A satisfies keyof : MixEnum.A +> : ^^^^^^^^^ +>MixEnum.A : MixEnum.A +> : ^^^^^^^^^ +>MixEnum : typeof MixEnum +> : ^^^^^^^^^^^^^^ +>A : MixEnum.A +> : ^^^^^^^^^ + + return 7 as const; +>7 as const : 7 +> : ^ +>7 : 7 +> : ^ + } + + [MixEnum.B satisfies keyof]() { +>[MixEnum.B satisfies keyof] : () => 8 +> : ^^^^^^^ +>MixEnum.B satisfies keyof : MixEnum.B +> : ^^^^^^^^^ +>MixEnum.B : MixEnum.B +> : ^^^^^^^^^ +>MixEnum : typeof MixEnum +> : ^^^^^^^^^^^^^^ +>B : MixEnum.B +> : ^^^^^^^^^ + + return 8 as const; +>8 as const : 8 +> : ^ +>8 : 8 +> : ^ + } + + [anything satisfies keyof]() { +>[anything satisfies keyof] : () => 9 +> : ^^^^^^^ +>anything satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>anything : any +> : ^^^ + + return 9 as const; +>9 as const : 9 +> : ^ +>9 : 9 +> : ^ + } + + [unk satisfies keyof]() { +>[unk satisfies keyof] : () => 10 +> : ^^^^^^^^ +>unk satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>unk : unknown +> : ^^^^^^^ + + return 10 as const; +>10 as const : 10 +> : ^^ +>10 : 10 +> : ^^ + } + + [basestr satisfies keyof]() { +>[basestr satisfies keyof] : () => 11 +> : ^^^^^^^^ +>basestr satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>basestr : string +> : ^^^^^^ + + return 11 as const; +>11 as const : 11 +> : ^^ +>11 : 11 +> : ^^ + } + + [basenum satisfies keyof]() { +>[basenum satisfies keyof] : () => 12 +> : ^^^^^^^^ +>basenum satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>basenum : number +> : ^^^^^^ + + return 12 as const; +>12 as const : 12 +> : ^^ +>12 : 12 +> : ^^ + } + + [bool satisfies keyof]() { +>[bool satisfies keyof] : () => 13 +> : ^^^^^^^^ +>bool satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>bool : boolean +> : ^^^^^^^ + + return 13 as const; +>13 as const : 13 +> : ^^ +>13 : 13 +> : ^^ + } + + [t satisfies keyof]() { +>[t satisfies keyof] : () => 14 +> : ^^^^^^^^ +>t satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>t : true +> : ^^^^ + + return 14 as const; +>14 as const : 14 +> : ^^ +>14 : 14 +> : ^^ + } + + [f satisfies keyof]() { +>[f satisfies keyof] : () => 15 +> : ^^^^^^^^ +>f satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>f : false +> : ^^^^^ + + return 15 as const; +>15 as const : 15 +> : ^^ +>15 : 15 +> : ^^ + } + + [n satisfies keyof]() { +>[n satisfies keyof] : () => 16 +> : ^^^^^^^^ +>n satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>n : null +> : ^^^^ + + return 16 as const; +>16 as const : 16 +> : ^^ +>16 : 16 +> : ^^ + } + + [u satisfies keyof]() { +>[u satisfies keyof] : () => 17 +> : ^^^^^^^^ +>u satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>u : undefined +> : ^^^^^^^^^ + + return 17 as const; +>17 as const : 17 +> : ^^ +>17 : 17 +> : ^^ + } + + [bigbase satisfies keyof]() { +>[bigbase satisfies keyof] : () => 18 +> : ^^^^^^^^ +>bigbase satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>bigbase : bigint +> : ^^^^^^ + + return 18 as const; +>18 as const : 18 +> : ^^ +>18 : 18 +> : ^^ + } + + [biglit satisfies keyof]() { +>[biglit satisfies keyof] : () => 19 +> : ^^^^^^^^ +>biglit satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>biglit : 22n +> : ^^^ + + return 19 as const; +>19 as const : 19 +> : ^^ +>19 : 19 +> : ^^ + } + + [symbase satisfies keyof]() { +>[symbase satisfies keyof] : () => 20 +> : ^^^^^^^^ +>symbase satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>symbase : symbol +> : ^^^^^^ + + return 20 as const; +>20 as const : 20 +> : ^^ +>20 : 20 +> : ^^ + } + + [nev satisfies keyof]() { +>[nev satisfies keyof] : () => 21 +> : ^^^^^^^^ +>nev satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>nev : never +> : ^^^^^ + + return 21 as const; +>21 as const : 21 +> : ^^ +>21 : 21 +> : ^^ + } + + [templateLit satisfies keyof]() { +>[templateLit satisfies keyof] : () => 22 +> : ^^^^^^^^ +>templateLit satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>templateLit : `aaa${string}` +> : ^^^^^^^^^^^^^^ + + return 22 as const; +>22 as const : 22 +> : ^^ +>22 : 22 +> : ^^ + } + + [mappingLit satisfies keyof]() { +>[mappingLit satisfies keyof] : () => 23 +> : ^^^^^^^^ +>mappingLit satisfies keyof : unique symbol +> : ^^^^^^^^^^^^^ +>mappingLit : Lowercase +> : ^^^^^^^^^^^^^^^^^ + + return 23 as const; +>23 as const : 23 +> : ^^ +>23 : 23 +> : ^^ + } +} + +const inst = new Foo(); +>inst : Foo +> : ^^^ +>new Foo() : Foo +> : ^^^ +>Foo : typeof Foo +> : ^^^^^^^^^^ + +export const results = [ +>results : readonly [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, any, 22, 23] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>[ inst[sym](), inst[num](), inst[str](), inst[union](), inst[NumEnum.A](), inst[StrEnum.A](), inst[MixEnum.A](), inst[MixEnum.B](), inst[anything](), inst[unk](), inst[basestr](), inst[basenum](), inst[bool](), inst[t](), inst[f](), inst[n](), inst[u](), inst[bigbase](), inst[biglit](), inst[symbase](), inst[nev](), // indexing by `never` always gives `never`, rather than the fallback index property inst[templateLit](), inst[mappingLit](), ] as const : readonly [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, any, 22, 23] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>[ inst[sym](), inst[num](), inst[str](), inst[union](), inst[NumEnum.A](), inst[StrEnum.A](), inst[MixEnum.A](), inst[MixEnum.B](), inst[anything](), inst[unk](), inst[basestr](), inst[basenum](), inst[bool](), inst[t](), inst[f](), inst[n](), inst[u](), inst[bigbase](), inst[biglit](), inst[symbase](), inst[nev](), // indexing by `never` always gives `never`, rather than the fallback index property inst[templateLit](), inst[mappingLit](), ] : readonly [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, any, 22, 23] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + inst[sym](), +>inst[sym]() : 1 +> : ^ +>inst[sym] : () => 1 +> : ^^^^^^^ +>inst : Foo +> : ^^^ +>sym : unique symbol +> : ^^^^^^^^^^^^^ + + inst[num](), +>inst[num]() : 2 +> : ^ +>inst[num] : () => 2 +> : ^^^^^^^ +>inst : Foo +> : ^^^ +>num : 1 +> : ^ + + inst[str](), +>inst[str]() : 3 +> : ^ +>inst[str] : () => 3 +> : ^^^^^^^ +>inst : Foo +> : ^^^ +>str : "f" +> : ^^^ + + inst[union](), +>inst[union]() : 4 +> : ^ +>inst[union] : () => 4 +> : ^^^^^^^ +>inst : Foo +> : ^^^ +>union : "answer" | 42 +> : ^^^^^^^^^^^^^ + + inst[NumEnum.A](), +>inst[NumEnum.A]() : 5 +> : ^ +>inst[NumEnum.A] : () => 5 +> : ^^^^^^^ +>inst : Foo +> : ^^^ +>NumEnum.A : NumEnum.A +> : ^^^^^^^^^ +>NumEnum : typeof NumEnum +> : ^^^^^^^^^^^^^^ +>A : NumEnum.A +> : ^^^^^^^^^ + + inst[StrEnum.A](), +>inst[StrEnum.A]() : 6 +> : ^ +>inst[StrEnum.A] : () => 6 +> : ^^^^^^^ +>inst : Foo +> : ^^^ +>StrEnum.A : StrEnum.A +> : ^^^^^^^^^ +>StrEnum : typeof StrEnum +> : ^^^^^^^^^^^^^^ +>A : StrEnum.A +> : ^^^^^^^^^ + + inst[MixEnum.A](), +>inst[MixEnum.A]() : 7 +> : ^ +>inst[MixEnum.A] : () => 7 +> : ^^^^^^^ +>inst : Foo +> : ^^^ +>MixEnum.A : MixEnum.A +> : ^^^^^^^^^ +>MixEnum : typeof MixEnum +> : ^^^^^^^^^^^^^^ +>A : MixEnum.A +> : ^^^^^^^^^ + + inst[MixEnum.B](), +>inst[MixEnum.B]() : 8 +> : ^ +>inst[MixEnum.B] : () => 8 +> : ^^^^^^^ +>inst : Foo +> : ^^^ +>MixEnum.B : MixEnum.B +> : ^^^^^^^^^ +>MixEnum : typeof MixEnum +> : ^^^^^^^^^^^^^^ +>B : MixEnum.B +> : ^^^^^^^^^ + + inst[anything](), +>inst[anything]() : 9 +> : ^ +>inst[anything] : () => 9 +> : ^^^^^^^ +>inst : Foo +> : ^^^ +>anything : any +> : ^^^ + + inst[unk](), +>inst[unk]() : 10 +> : ^^ +>inst[unk] : () => 10 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>unk : unknown +> : ^^^^^^^ + + inst[basestr](), +>inst[basestr]() : 11 +> : ^^ +>inst[basestr] : () => 11 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>basestr : string +> : ^^^^^^ + + inst[basenum](), +>inst[basenum]() : 12 +> : ^^ +>inst[basenum] : () => 12 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>basenum : number +> : ^^^^^^ + + inst[bool](), +>inst[bool]() : 13 +> : ^^ +>inst[bool] : () => 13 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>bool : boolean +> : ^^^^^^^ + + inst[t](), +>inst[t]() : 14 +> : ^^ +>inst[t] : () => 14 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>t : true +> : ^^^^ + + inst[f](), +>inst[f]() : 15 +> : ^^ +>inst[f] : () => 15 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>f : false +> : ^^^^^ + + inst[n](), +>inst[n]() : 16 +> : ^^ +>inst[n] : () => 16 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>n : null +> : ^^^^ + + inst[u](), +>inst[u]() : 17 +> : ^^ +>inst[u] : () => 17 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>u : undefined +> : ^^^^^^^^^ + + inst[bigbase](), +>inst[bigbase]() : 18 +> : ^^ +>inst[bigbase] : () => 18 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>bigbase : bigint +> : ^^^^^^ + + inst[biglit](), +>inst[biglit]() : 19 +> : ^^ +>inst[biglit] : () => 19 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>biglit : 22n +> : ^^^ + + inst[symbase](), +>inst[symbase]() : 20 +> : ^^ +>inst[symbase] : () => 20 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>symbase : symbol +> : ^^^^^^ + + inst[nev](), // indexing by `never` always gives `never`, rather than the fallback index property +>inst[nev]() : any +> : ^^^ +>inst[nev] : never +> : ^^^^^ +>inst : Foo +> : ^^^ +>nev : never +> : ^^^^^ + + inst[templateLit](), +>inst[templateLit]() : 22 +> : ^^ +>inst[templateLit] : () => 22 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>templateLit : `aaa${string}` +> : ^^^^^^^^^^^^^^ + + inst[mappingLit](), +>inst[mappingLit]() : 23 +> : ^^ +>inst[mappingLit] : () => 23 +> : ^^^^^^^^ +>inst : Foo +> : ^^^ +>mappingLit : Lowercase +> : ^^^^^^^^^^^^^^^^^ + +] as const; + + + diff --git a/tests/cases/conformance/types/keyof/satisfiesKeyof1.ts b/tests/cases/conformance/types/keyof/satisfiesKeyof1.ts new file mode 100644 index 0000000000000..19b0a4307f3d8 --- /dev/null +++ b/tests/cases/conformance/types/keyof/satisfiesKeyof1.ts @@ -0,0 +1,36 @@ +// @declaration: true +// @target: es6 +// intended usage +const x = Symbol(); + +export class Foo { + [x satisfies keyof]() { + return 1; + } +} + +export const usage1 = new Foo()[x](); + +// errors on missing +import {y} from "missing"; +export class Bar { + [y satisfies keyof]() { + return 1; + } +} + +export const usage2 = new Bar()[y](); + +// errors on wrong types +const z = Math.random() ? 1 : "a"; +export class Baz { + [z satisfies keyof]() { + return 1; + } +} + +export const usage3 = new Baz()[z](); + +// error on satisfies keyof outside computed name + +export const a = 0 satisfies keyof; diff --git a/tests/cases/conformance/types/keyof/satisfiesKeyofGenerics.ts b/tests/cases/conformance/types/keyof/satisfiesKeyofGenerics.ts new file mode 100644 index 0000000000000..b3b9df48c34be --- /dev/null +++ b/tests/cases/conformance/types/keyof/satisfiesKeyofGenerics.ts @@ -0,0 +1,112 @@ +// @declaration: true +export function f< + T, + U extends string, + V extends "onefield", + W extends "afield" | "bfield", +>( + p1: T, + p2: T & string, + p3: T & "f", + p4: T | string, + p5: T | "g", + p6: Extract, + + p7: U, + p8: U & string, + p9: U & "f", + p10: U | string, + p11: U | "g", + p12: Extract, + + p13: V, + p14: V & string, + p15: V & "onefield", + p16: V | string, + p17: V | "onefield", + p18: Extract, + + p19: W, + p20: W & string, + p21: W & "afield", // reduction rules for generics extending unions will simplify this to just "afield" where possible, so should be the only one that works without error + p22: W | string, + p23: W | "afield", + p24: Extract, +) { + return [ + class Foo { + [p1 satisfies keyof]() { + return 1 as const; + } + [p2 satisfies keyof]() { + return 2 as const; + } + [p3 satisfies keyof]() { + return 3 as const; + } + [p4 satisfies keyof]() { + return 4 as const; + } + [p5 satisfies keyof]() { + return 5 as const; + } + [p6 satisfies keyof]() { + return 6 as const; + } + [p7 satisfies keyof]() { + return 7 as const; + } + [p8 satisfies keyof]() { + return 8 as const; + } + [p9 satisfies keyof]() { + return 9 as const; + } + [p10 satisfies keyof]() { + return 10 as const; + } + [p11 satisfies keyof]() { + return 11 as const; + } + [p12 satisfies keyof]() { + return 12 as const; + } + [p13 satisfies keyof]() { + return 13 as const; + } + [p14 satisfies keyof]() { + return 14 as const; + } + [p15 satisfies keyof]() { + return 15 as const; + } + [p16 satisfies keyof]() { + return 16 as const; + } + [p17 satisfies keyof]() { + return 17 as const; + } + [p18 satisfies keyof]() { + return 18 as const; + } + [p19 satisfies keyof]() { + return 19 as const; + } + [p20 satisfies keyof]() { + return 20 as const; + } + [p21 satisfies keyof]() { + return 21 as const; + } + [p22 satisfies keyof]() { + return 22 as const; + } + [p23 satisfies keyof]() { + return 23 as const; + } + [p24 satisfies keyof]() { + return 24 as const; + } + } + ] as const; +} \ No newline at end of file diff --git a/tests/cases/conformance/types/keyof/satisfiesKeyofInputTypes.ts b/tests/cases/conformance/types/keyof/satisfiesKeyofInputTypes.ts new file mode 100644 index 0000000000000..410dc67135654 --- /dev/null +++ b/tests/cases/conformance/types/keyof/satisfiesKeyofInputTypes.ts @@ -0,0 +1,162 @@ +// @declaration: true +// @strict: true +// @target: es2020 + +const sym = Symbol(); +const num = 1; +const str = "f"; +const union = Math.random() > 0.5 ? "answer" : 42; + +enum NumEnum { + A, + B, +} + +enum StrEnum { + A = "a", + B = "b" +} + +enum MixEnum { + A = 10, + B = "bb", +} + +const anything = null as any; +const unk = null as any as unknown; +const basestr = "" as string; +const basenum = 11 as number; +const bool = true as boolean; +const t = true; +const f = false; +const n = null; +const u = undefined; +const bigbase = 1n as bigint; +const biglit = 22n; +const symbase = null as any as symbol; +const nev = null as never; +const templateLit = `aaabb` as `aaa${string}`; +const mappingLit = `bbbaa` as Lowercase; + +export class Foo { + [sym satisfies keyof]() { + return 1 as const; + } + + [num satisfies keyof]() { + return 2 as const; + } + + [str satisfies keyof]() { + return 3 as const; + } + + [union satisfies keyof]() { + return 4 as const; + } + + [NumEnum.A satisfies keyof]() { + return 5 as const; + } + + [StrEnum.A satisfies keyof]() { + return 6 as const; + } + + [MixEnum.A satisfies keyof]() { + return 7 as const; + } + + [MixEnum.B satisfies keyof]() { + return 8 as const; + } + + [anything satisfies keyof]() { + return 9 as const; + } + + [unk satisfies keyof]() { + return 10 as const; + } + + [basestr satisfies keyof]() { + return 11 as const; + } + + [basenum satisfies keyof]() { + return 12 as const; + } + + [bool satisfies keyof]() { + return 13 as const; + } + + [t satisfies keyof]() { + return 14 as const; + } + + [f satisfies keyof]() { + return 15 as const; + } + + [n satisfies keyof]() { + return 16 as const; + } + + [u satisfies keyof]() { + return 17 as const; + } + + [bigbase satisfies keyof]() { + return 18 as const; + } + + [biglit satisfies keyof]() { + return 19 as const; + } + + [symbase satisfies keyof]() { + return 20 as const; + } + + [nev satisfies keyof]() { + return 21 as const; + } + + [templateLit satisfies keyof]() { + return 22 as const; + } + + [mappingLit satisfies keyof]() { + return 23 as const; + } +} + +const inst = new Foo(); +export const results = [ + inst[sym](), + inst[num](), + inst[str](), + inst[union](), + inst[NumEnum.A](), + inst[StrEnum.A](), + inst[MixEnum.A](), + inst[MixEnum.B](), + inst[anything](), + inst[unk](), + inst[basestr](), + inst[basenum](), + inst[bool](), + inst[t](), + inst[f](), + inst[n](), + inst[u](), + inst[bigbase](), + inst[biglit](), + inst[symbase](), + inst[nev](), // indexing by `never` always gives `never`, rather than the fallback index property + inst[templateLit](), + inst[mappingLit](), +] as const; + + From 2119aed71f25405a2ee1650350fe1312c60884bd Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 11 Jun 2024 11:26:21 -0700 Subject: [PATCH 2/2] Format --- src/compiler/checker.ts | 2 +- src/compiler/transformers/declarations.ts | 2 +- src/compiler/utilities.ts | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 37413269764d4..dd38b8306f1bd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -715,6 +715,7 @@ import { isRightSideOfQualifiedNameOrPropertyAccessOrJSDocMemberName, isSameEntityName, isSatisfiesExpression, + isSatisfiesKeyofExpression, isSetAccessor, isSetAccessorDeclaration, isShorthandAmbientModuleSymbol, @@ -1109,7 +1110,6 @@ import { WideningContext, WithStatement, YieldExpression, - isSatisfiesKeyofExpression, } from "./_namespaces/ts.js"; import * as moduleSpecifiers from "./_namespaces/ts.moduleSpecifiers.js"; import * as performance from "./_namespaces/ts.performance.js"; diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 1343fc9e1a46d..66d110ed93dd9 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1805,7 +1805,7 @@ export function transformDeclarations(context: TransformationContext) { if (returnValue && nameExpr !== entityName) { const updated = factory.updateComputedPropertyName(decl.name, nameExpr) as LateBoundName; result = factory.cloneNode(returnValue); - (result as Mutable).name = updated as Extract["name"] & LateBoundName; + (result as Mutable).name = updated as Extract["name"] & LateBoundName; } if (!suppressNewDiagnosticContexts) { getSymbolAccessibilityDiagnostic = oldDiag!; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 8170ee721fe82..e5a428243f55f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -494,6 +494,7 @@ import { ReturnStatement, returnUndefined, SatisfiesExpression, + SatisfiesKeyofEntityNameExpression, ScriptKind, ScriptTarget, semanticDiagnosticsOptionDeclarations, @@ -585,7 +586,6 @@ import { WriteFileCallback, WriteFileCallbackData, YieldExpression, - SatisfiesKeyofEntityNameExpression, } from "./_namespaces/ts.js"; /** @internal */ @@ -11669,5 +11669,4 @@ export function hasInferredType(node: Node): node is HasInferredType { /** @internal */ export function isSatisfiesKeyofExpression(node: Node): node is SatisfiesKeyofEntityNameExpression { return node.kind === SyntaxKind.SatisfiesExpression && (node as SatisfiesExpression).type.kind === SyntaxKind.KeyOfKeyword && isEntityNameExpression((node as SatisfiesExpression).expression); - -} \ No newline at end of file +}