diff --git a/internal/ast/ast.go b/internal/ast/ast.go index 3d6dbcffcc..acd5d37875 100644 --- a/internal/ast/ast.go +++ b/internal/ast/ast.go @@ -573,6 +573,8 @@ func (n *Node) TypeParameterList() *NodeList { return n.AsTypeAliasDeclaration().TypeParameters case KindJSDocTemplateTag: return n.AsJSDocTemplateTag().TypeParameters + case KindQuantifiedType: + return n.AsQuantifiedTypeNode().TypeParameters default: funcLike := n.FunctionLikeData() if funcLike != nil { @@ -1750,6 +1752,10 @@ func (n *Node) AsConstructorTypeNode() *ConstructorTypeNode { return n.data.(*ConstructorTypeNode) } +func (n *Node) AsQuantifiedTypeNode() *QuantifiedTypeNode { + return n.data.(*QuantifiedTypeNode) +} + func (n *Node) AsTypeQueryNode() *TypeQueryNode { return n.data.(*TypeQueryNode) } @@ -8871,6 +8877,41 @@ func IsTemplateLiteralTypeSpan(node *Node) bool { return node.Kind == KindTemplateLiteralTypeSpan } +// QuantifiedTypeNode + +type QuantifiedTypeNode struct { + TypeNodeBase + LocalsContainerBase + TypeParameters *NodeList // NodeList[*TypeParameterDeclarationNode] + BaseType *TypeNode +} + +func (f *NodeFactory) NewQuantifiedTypeNode(typeParameters *NodeList, baseTypeNode *TypeNode) *Node { + data := &QuantifiedTypeNode{} + data.TypeParameters = typeParameters + data.BaseType = baseTypeNode + return f.newNode(KindQuantifiedType, data) +} + +func (f *NodeFactory) UpdateQuantifiedTypeNode(node *QuantifiedTypeNode, typeParameters *NodeList, baseTypeNode *TypeNode) *Node { + if typeParameters != node.TypeParameters || baseTypeNode != node.BaseType { + return updateNode(f.NewQuantifiedTypeNode(typeParameters, baseTypeNode), node.AsNode(), f.hooks) + } + return node.AsNode() +} + +func (node *QuantifiedTypeNode) ForEachChild(v Visitor) bool { + return visitNodeList(v, node.TypeParameters) || visit(v, node.BaseType) +} + +func (node *QuantifiedTypeNode) VisitEachChild(v *NodeVisitor) *Node { + return v.Factory.UpdateQuantifiedTypeNode(node, v.visitNodes(node.TypeParameters), v.visitNode(node.BaseType)) +} + +func (node *QuantifiedTypeNode) Clone(f NodeFactoryCoercible) *Node { + return cloneNode(f.AsNodeFactory().NewQuantifiedTypeNode(node.TypeParameters, node.BaseType), node.AsNode(), f.AsNodeFactory().hooks) +} + // SyntheticExpression type SyntheticExpression struct { diff --git a/internal/ast/kind.go b/internal/ast/kind.go index ed98bd68ff..6a359cefed 100644 --- a/internal/ast/kind.go +++ b/internal/ast/kind.go @@ -226,6 +226,7 @@ const ( KindNamedTupleMember KindTemplateLiteralType KindTemplateLiteralTypeSpan + KindQuantifiedType KindImportType // Binding patterns KindObjectBindingPattern diff --git a/internal/ast/kind_stringer_generated.go b/internal/ast/kind_stringer_generated.go index 3430cc2cb1..4a6ac4ed3a 100644 --- a/internal/ast/kind_stringer_generated.go +++ b/internal/ast/kind_stringer_generated.go @@ -214,160 +214,161 @@ func _() { _ = x[KindNamedTupleMember-203] _ = x[KindTemplateLiteralType-204] _ = x[KindTemplateLiteralTypeSpan-205] - _ = x[KindImportType-206] - _ = x[KindObjectBindingPattern-207] - _ = x[KindArrayBindingPattern-208] - _ = x[KindBindingElement-209] - _ = x[KindArrayLiteralExpression-210] - _ = x[KindObjectLiteralExpression-211] - _ = x[KindPropertyAccessExpression-212] - _ = x[KindElementAccessExpression-213] - _ = x[KindCallExpression-214] - _ = x[KindNewExpression-215] - _ = x[KindTaggedTemplateExpression-216] - _ = x[KindTypeAssertionExpression-217] - _ = x[KindParenthesizedExpression-218] - _ = x[KindFunctionExpression-219] - _ = x[KindArrowFunction-220] - _ = x[KindDeleteExpression-221] - _ = x[KindTypeOfExpression-222] - _ = x[KindVoidExpression-223] - _ = x[KindAwaitExpression-224] - _ = x[KindPrefixUnaryExpression-225] - _ = x[KindPostfixUnaryExpression-226] - _ = x[KindBinaryExpression-227] - _ = x[KindConditionalExpression-228] - _ = x[KindTemplateExpression-229] - _ = x[KindYieldExpression-230] - _ = x[KindSpreadElement-231] - _ = x[KindClassExpression-232] - _ = x[KindOmittedExpression-233] - _ = x[KindExpressionWithTypeArguments-234] - _ = x[KindAsExpression-235] - _ = x[KindNonNullExpression-236] - _ = x[KindMetaProperty-237] - _ = x[KindSyntheticExpression-238] - _ = x[KindSatisfiesExpression-239] - _ = x[KindTemplateSpan-240] - _ = x[KindSemicolonClassElement-241] - _ = x[KindBlock-242] - _ = x[KindEmptyStatement-243] - _ = x[KindVariableStatement-244] - _ = x[KindExpressionStatement-245] - _ = x[KindIfStatement-246] - _ = x[KindDoStatement-247] - _ = x[KindWhileStatement-248] - _ = x[KindForStatement-249] - _ = x[KindForInStatement-250] - _ = x[KindForOfStatement-251] - _ = x[KindContinueStatement-252] - _ = x[KindBreakStatement-253] - _ = x[KindReturnStatement-254] - _ = x[KindWithStatement-255] - _ = x[KindSwitchStatement-256] - _ = x[KindLabeledStatement-257] - _ = x[KindThrowStatement-258] - _ = x[KindTryStatement-259] - _ = x[KindDebuggerStatement-260] - _ = x[KindVariableDeclaration-261] - _ = x[KindVariableDeclarationList-262] - _ = x[KindFunctionDeclaration-263] - _ = x[KindClassDeclaration-264] - _ = x[KindInterfaceDeclaration-265] - _ = x[KindTypeAliasDeclaration-266] - _ = x[KindEnumDeclaration-267] - _ = x[KindModuleDeclaration-268] - _ = x[KindModuleBlock-269] - _ = x[KindCaseBlock-270] - _ = x[KindNamespaceExportDeclaration-271] - _ = x[KindImportEqualsDeclaration-272] - _ = x[KindImportDeclaration-273] - _ = x[KindImportClause-274] - _ = x[KindNamespaceImport-275] - _ = x[KindNamedImports-276] - _ = x[KindImportSpecifier-277] - _ = x[KindExportAssignment-278] - _ = x[KindExportDeclaration-279] - _ = x[KindNamedExports-280] - _ = x[KindNamespaceExport-281] - _ = x[KindExportSpecifier-282] - _ = x[KindMissingDeclaration-283] - _ = x[KindExternalModuleReference-284] - _ = x[KindJsxElement-285] - _ = x[KindJsxSelfClosingElement-286] - _ = x[KindJsxOpeningElement-287] - _ = x[KindJsxClosingElement-288] - _ = x[KindJsxFragment-289] - _ = x[KindJsxOpeningFragment-290] - _ = x[KindJsxClosingFragment-291] - _ = x[KindJsxAttribute-292] - _ = x[KindJsxAttributes-293] - _ = x[KindJsxSpreadAttribute-294] - _ = x[KindJsxExpression-295] - _ = x[KindJsxNamespacedName-296] - _ = x[KindCaseClause-297] - _ = x[KindDefaultClause-298] - _ = x[KindHeritageClause-299] - _ = x[KindCatchClause-300] - _ = x[KindImportAttributes-301] - _ = x[KindImportAttribute-302] - _ = x[KindPropertyAssignment-303] - _ = x[KindShorthandPropertyAssignment-304] - _ = x[KindSpreadAssignment-305] - _ = x[KindEnumMember-306] - _ = x[KindSourceFile-307] - _ = x[KindJSDocTypeExpression-308] - _ = x[KindJSDocNameReference-309] - _ = x[KindJSDocMemberName-310] - _ = x[KindJSDocAllType-311] - _ = x[KindJSDocNullableType-312] - _ = x[KindJSDocNonNullableType-313] - _ = x[KindJSDocOptionalType-314] - _ = x[KindJSDocVariadicType-315] - _ = x[KindJSDoc-316] - _ = x[KindJSDocText-317] - _ = x[KindJSDocTypeLiteral-318] - _ = x[KindJSDocSignature-319] - _ = x[KindJSDocLink-320] - _ = x[KindJSDocLinkCode-321] - _ = x[KindJSDocLinkPlain-322] - _ = x[KindJSDocTag-323] - _ = x[KindJSDocAugmentsTag-324] - _ = x[KindJSDocImplementsTag-325] - _ = x[KindJSDocDeprecatedTag-326] - _ = x[KindJSDocPublicTag-327] - _ = x[KindJSDocPrivateTag-328] - _ = x[KindJSDocProtectedTag-329] - _ = x[KindJSDocReadonlyTag-330] - _ = x[KindJSDocOverrideTag-331] - _ = x[KindJSDocCallbackTag-332] - _ = x[KindJSDocOverloadTag-333] - _ = x[KindJSDocParameterTag-334] - _ = x[KindJSDocReturnTag-335] - _ = x[KindJSDocThisTag-336] - _ = x[KindJSDocTypeTag-337] - _ = x[KindJSDocTemplateTag-338] - _ = x[KindJSDocTypedefTag-339] - _ = x[KindJSDocSeeTag-340] - _ = x[KindJSDocPropertyTag-341] - _ = x[KindJSDocSatisfiesTag-342] - _ = x[KindJSDocImportTag-343] - _ = x[KindSyntaxList-344] - _ = x[KindJSTypeAliasDeclaration-345] - _ = x[KindJSExportAssignment-346] - _ = x[KindCommonJSExport-347] - _ = x[KindJSImportDeclaration-348] - _ = x[KindNotEmittedStatement-349] - _ = x[KindPartiallyEmittedExpression-350] - _ = x[KindCommaListExpression-351] - _ = x[KindSyntheticReferenceExpression-352] - _ = x[KindNotEmittedTypeElement-353] - _ = x[KindCount-354] + _ = x[KindQuantifiedType-206] + _ = x[KindImportType-207] + _ = x[KindObjectBindingPattern-208] + _ = x[KindArrayBindingPattern-209] + _ = x[KindBindingElement-210] + _ = x[KindArrayLiteralExpression-211] + _ = x[KindObjectLiteralExpression-212] + _ = x[KindPropertyAccessExpression-213] + _ = x[KindElementAccessExpression-214] + _ = x[KindCallExpression-215] + _ = x[KindNewExpression-216] + _ = x[KindTaggedTemplateExpression-217] + _ = x[KindTypeAssertionExpression-218] + _ = x[KindParenthesizedExpression-219] + _ = x[KindFunctionExpression-220] + _ = x[KindArrowFunction-221] + _ = x[KindDeleteExpression-222] + _ = x[KindTypeOfExpression-223] + _ = x[KindVoidExpression-224] + _ = x[KindAwaitExpression-225] + _ = x[KindPrefixUnaryExpression-226] + _ = x[KindPostfixUnaryExpression-227] + _ = x[KindBinaryExpression-228] + _ = x[KindConditionalExpression-229] + _ = x[KindTemplateExpression-230] + _ = x[KindYieldExpression-231] + _ = x[KindSpreadElement-232] + _ = x[KindClassExpression-233] + _ = x[KindOmittedExpression-234] + _ = x[KindExpressionWithTypeArguments-235] + _ = x[KindAsExpression-236] + _ = x[KindNonNullExpression-237] + _ = x[KindMetaProperty-238] + _ = x[KindSyntheticExpression-239] + _ = x[KindSatisfiesExpression-240] + _ = x[KindTemplateSpan-241] + _ = x[KindSemicolonClassElement-242] + _ = x[KindBlock-243] + _ = x[KindEmptyStatement-244] + _ = x[KindVariableStatement-245] + _ = x[KindExpressionStatement-246] + _ = x[KindIfStatement-247] + _ = x[KindDoStatement-248] + _ = x[KindWhileStatement-249] + _ = x[KindForStatement-250] + _ = x[KindForInStatement-251] + _ = x[KindForOfStatement-252] + _ = x[KindContinueStatement-253] + _ = x[KindBreakStatement-254] + _ = x[KindReturnStatement-255] + _ = x[KindWithStatement-256] + _ = x[KindSwitchStatement-257] + _ = x[KindLabeledStatement-258] + _ = x[KindThrowStatement-259] + _ = x[KindTryStatement-260] + _ = x[KindDebuggerStatement-261] + _ = x[KindVariableDeclaration-262] + _ = x[KindVariableDeclarationList-263] + _ = x[KindFunctionDeclaration-264] + _ = x[KindClassDeclaration-265] + _ = x[KindInterfaceDeclaration-266] + _ = x[KindTypeAliasDeclaration-267] + _ = x[KindEnumDeclaration-268] + _ = x[KindModuleDeclaration-269] + _ = x[KindModuleBlock-270] + _ = x[KindCaseBlock-271] + _ = x[KindNamespaceExportDeclaration-272] + _ = x[KindImportEqualsDeclaration-273] + _ = x[KindImportDeclaration-274] + _ = x[KindImportClause-275] + _ = x[KindNamespaceImport-276] + _ = x[KindNamedImports-277] + _ = x[KindImportSpecifier-278] + _ = x[KindExportAssignment-279] + _ = x[KindExportDeclaration-280] + _ = x[KindNamedExports-281] + _ = x[KindNamespaceExport-282] + _ = x[KindExportSpecifier-283] + _ = x[KindMissingDeclaration-284] + _ = x[KindExternalModuleReference-285] + _ = x[KindJsxElement-286] + _ = x[KindJsxSelfClosingElement-287] + _ = x[KindJsxOpeningElement-288] + _ = x[KindJsxClosingElement-289] + _ = x[KindJsxFragment-290] + _ = x[KindJsxOpeningFragment-291] + _ = x[KindJsxClosingFragment-292] + _ = x[KindJsxAttribute-293] + _ = x[KindJsxAttributes-294] + _ = x[KindJsxSpreadAttribute-295] + _ = x[KindJsxExpression-296] + _ = x[KindJsxNamespacedName-297] + _ = x[KindCaseClause-298] + _ = x[KindDefaultClause-299] + _ = x[KindHeritageClause-300] + _ = x[KindCatchClause-301] + _ = x[KindImportAttributes-302] + _ = x[KindImportAttribute-303] + _ = x[KindPropertyAssignment-304] + _ = x[KindShorthandPropertyAssignment-305] + _ = x[KindSpreadAssignment-306] + _ = x[KindEnumMember-307] + _ = x[KindSourceFile-308] + _ = x[KindJSDocTypeExpression-309] + _ = x[KindJSDocNameReference-310] + _ = x[KindJSDocMemberName-311] + _ = x[KindJSDocAllType-312] + _ = x[KindJSDocNullableType-313] + _ = x[KindJSDocNonNullableType-314] + _ = x[KindJSDocOptionalType-315] + _ = x[KindJSDocVariadicType-316] + _ = x[KindJSDoc-317] + _ = x[KindJSDocText-318] + _ = x[KindJSDocTypeLiteral-319] + _ = x[KindJSDocSignature-320] + _ = x[KindJSDocLink-321] + _ = x[KindJSDocLinkCode-322] + _ = x[KindJSDocLinkPlain-323] + _ = x[KindJSDocTag-324] + _ = x[KindJSDocAugmentsTag-325] + _ = x[KindJSDocImplementsTag-326] + _ = x[KindJSDocDeprecatedTag-327] + _ = x[KindJSDocPublicTag-328] + _ = x[KindJSDocPrivateTag-329] + _ = x[KindJSDocProtectedTag-330] + _ = x[KindJSDocReadonlyTag-331] + _ = x[KindJSDocOverrideTag-332] + _ = x[KindJSDocCallbackTag-333] + _ = x[KindJSDocOverloadTag-334] + _ = x[KindJSDocParameterTag-335] + _ = x[KindJSDocReturnTag-336] + _ = x[KindJSDocThisTag-337] + _ = x[KindJSDocTypeTag-338] + _ = x[KindJSDocTemplateTag-339] + _ = x[KindJSDocTypedefTag-340] + _ = x[KindJSDocSeeTag-341] + _ = x[KindJSDocPropertyTag-342] + _ = x[KindJSDocSatisfiesTag-343] + _ = x[KindJSDocImportTag-344] + _ = x[KindSyntaxList-345] + _ = x[KindJSTypeAliasDeclaration-346] + _ = x[KindJSExportAssignment-347] + _ = x[KindCommonJSExport-348] + _ = x[KindJSImportDeclaration-349] + _ = x[KindNotEmittedStatement-350] + _ = x[KindPartiallyEmittedExpression-351] + _ = x[KindCommaListExpression-352] + _ = x[KindSyntheticReferenceExpression-353] + _ = x[KindNotEmittedTypeElement-354] + _ = x[KindCount-355] } -const _Kind_name = "KindUnknownKindEndOfFileKindSingleLineCommentTriviaKindMultiLineCommentTriviaKindNewLineTriviaKindWhitespaceTriviaKindConflictMarkerTriviaKindNonTextFileMarkerTriviaKindNumericLiteralKindBigIntLiteralKindStringLiteralKindJsxTextKindJsxTextAllWhiteSpacesKindRegularExpressionLiteralKindNoSubstitutionTemplateLiteralKindTemplateHeadKindTemplateMiddleKindTemplateTailKindOpenBraceTokenKindCloseBraceTokenKindOpenParenTokenKindCloseParenTokenKindOpenBracketTokenKindCloseBracketTokenKindDotTokenKindDotDotDotTokenKindSemicolonTokenKindCommaTokenKindQuestionDotTokenKindLessThanTokenKindLessThanSlashTokenKindGreaterThanTokenKindLessThanEqualsTokenKindGreaterThanEqualsTokenKindEqualsEqualsTokenKindExclamationEqualsTokenKindEqualsEqualsEqualsTokenKindExclamationEqualsEqualsTokenKindEqualsGreaterThanTokenKindPlusTokenKindMinusTokenKindAsteriskTokenKindAsteriskAsteriskTokenKindSlashTokenKindPercentTokenKindPlusPlusTokenKindMinusMinusTokenKindLessThanLessThanTokenKindGreaterThanGreaterThanTokenKindGreaterThanGreaterThanGreaterThanTokenKindAmpersandTokenKindBarTokenKindCaretTokenKindExclamationTokenKindTildeTokenKindAmpersandAmpersandTokenKindBarBarTokenKindQuestionTokenKindColonTokenKindAtTokenKindQuestionQuestionTokenKindBacktickTokenKindHashTokenKindEqualsTokenKindPlusEqualsTokenKindMinusEqualsTokenKindAsteriskEqualsTokenKindAsteriskAsteriskEqualsTokenKindSlashEqualsTokenKindPercentEqualsTokenKindLessThanLessThanEqualsTokenKindGreaterThanGreaterThanEqualsTokenKindGreaterThanGreaterThanGreaterThanEqualsTokenKindAmpersandEqualsTokenKindBarEqualsTokenKindBarBarEqualsTokenKindAmpersandAmpersandEqualsTokenKindQuestionQuestionEqualsTokenKindCaretEqualsTokenKindIdentifierKindPrivateIdentifierKindJSDocCommentTextTokenKindBreakKeywordKindCaseKeywordKindCatchKeywordKindClassKeywordKindConstKeywordKindContinueKeywordKindDebuggerKeywordKindDefaultKeywordKindDeleteKeywordKindDoKeywordKindElseKeywordKindEnumKeywordKindExportKeywordKindExtendsKeywordKindFalseKeywordKindFinallyKeywordKindForKeywordKindFunctionKeywordKindIfKeywordKindImportKeywordKindInKeywordKindInstanceOfKeywordKindNewKeywordKindNullKeywordKindReturnKeywordKindSuperKeywordKindSwitchKeywordKindThisKeywordKindThrowKeywordKindTrueKeywordKindTryKeywordKindTypeOfKeywordKindVarKeywordKindVoidKeywordKindWhileKeywordKindWithKeywordKindImplementsKeywordKindInterfaceKeywordKindLetKeywordKindPackageKeywordKindPrivateKeywordKindProtectedKeywordKindPublicKeywordKindStaticKeywordKindYieldKeywordKindAbstractKeywordKindAccessorKeywordKindAsKeywordKindAssertsKeywordKindAssertKeywordKindAnyKeywordKindAsyncKeywordKindAwaitKeywordKindBooleanKeywordKindConstructorKeywordKindDeclareKeywordKindGetKeywordKindImmediateKeywordKindInferKeywordKindIntrinsicKeywordKindIsKeywordKindKeyOfKeywordKindModuleKeywordKindNamespaceKeywordKindNeverKeywordKindOutKeywordKindReadonlyKeywordKindRequireKeywordKindNumberKeywordKindObjectKeywordKindSatisfiesKeywordKindSetKeywordKindStringKeywordKindSymbolKeywordKindTypeKeywordKindUndefinedKeywordKindUniqueKeywordKindUnknownKeywordKindUsingKeywordKindFromKeywordKindGlobalKeywordKindBigIntKeywordKindOverrideKeywordKindOfKeywordKindDeferKeywordKindQualifiedNameKindComputedPropertyNameKindTypeParameterKindParameterKindDecoratorKindPropertySignatureKindPropertyDeclarationKindMethodSignatureKindMethodDeclarationKindClassStaticBlockDeclarationKindConstructorKindGetAccessorKindSetAccessorKindCallSignatureKindConstructSignatureKindIndexSignatureKindTypePredicateKindTypeReferenceKindFunctionTypeKindConstructorTypeKindTypeQueryKindTypeLiteralKindArrayTypeKindTupleTypeKindOptionalTypeKindRestTypeKindUnionTypeKindIntersectionTypeKindConditionalTypeKindInferTypeKindParenthesizedTypeKindThisTypeKindTypeOperatorKindIndexedAccessTypeKindMappedTypeKindLiteralTypeKindNamedTupleMemberKindTemplateLiteralTypeKindTemplateLiteralTypeSpanKindImportTypeKindObjectBindingPatternKindArrayBindingPatternKindBindingElementKindArrayLiteralExpressionKindObjectLiteralExpressionKindPropertyAccessExpressionKindElementAccessExpressionKindCallExpressionKindNewExpressionKindTaggedTemplateExpressionKindTypeAssertionExpressionKindParenthesizedExpressionKindFunctionExpressionKindArrowFunctionKindDeleteExpressionKindTypeOfExpressionKindVoidExpressionKindAwaitExpressionKindPrefixUnaryExpressionKindPostfixUnaryExpressionKindBinaryExpressionKindConditionalExpressionKindTemplateExpressionKindYieldExpressionKindSpreadElementKindClassExpressionKindOmittedExpressionKindExpressionWithTypeArgumentsKindAsExpressionKindNonNullExpressionKindMetaPropertyKindSyntheticExpressionKindSatisfiesExpressionKindTemplateSpanKindSemicolonClassElementKindBlockKindEmptyStatementKindVariableStatementKindExpressionStatementKindIfStatementKindDoStatementKindWhileStatementKindForStatementKindForInStatementKindForOfStatementKindContinueStatementKindBreakStatementKindReturnStatementKindWithStatementKindSwitchStatementKindLabeledStatementKindThrowStatementKindTryStatementKindDebuggerStatementKindVariableDeclarationKindVariableDeclarationListKindFunctionDeclarationKindClassDeclarationKindInterfaceDeclarationKindTypeAliasDeclarationKindEnumDeclarationKindModuleDeclarationKindModuleBlockKindCaseBlockKindNamespaceExportDeclarationKindImportEqualsDeclarationKindImportDeclarationKindImportClauseKindNamespaceImportKindNamedImportsKindImportSpecifierKindExportAssignmentKindExportDeclarationKindNamedExportsKindNamespaceExportKindExportSpecifierKindMissingDeclarationKindExternalModuleReferenceKindJsxElementKindJsxSelfClosingElementKindJsxOpeningElementKindJsxClosingElementKindJsxFragmentKindJsxOpeningFragmentKindJsxClosingFragmentKindJsxAttributeKindJsxAttributesKindJsxSpreadAttributeKindJsxExpressionKindJsxNamespacedNameKindCaseClauseKindDefaultClauseKindHeritageClauseKindCatchClauseKindImportAttributesKindImportAttributeKindPropertyAssignmentKindShorthandPropertyAssignmentKindSpreadAssignmentKindEnumMemberKindSourceFileKindJSDocTypeExpressionKindJSDocNameReferenceKindJSDocMemberNameKindJSDocAllTypeKindJSDocNullableTypeKindJSDocNonNullableTypeKindJSDocOptionalTypeKindJSDocVariadicTypeKindJSDocKindJSDocTextKindJSDocTypeLiteralKindJSDocSignatureKindJSDocLinkKindJSDocLinkCodeKindJSDocLinkPlainKindJSDocTagKindJSDocAugmentsTagKindJSDocImplementsTagKindJSDocDeprecatedTagKindJSDocPublicTagKindJSDocPrivateTagKindJSDocProtectedTagKindJSDocReadonlyTagKindJSDocOverrideTagKindJSDocCallbackTagKindJSDocOverloadTagKindJSDocParameterTagKindJSDocReturnTagKindJSDocThisTagKindJSDocTypeTagKindJSDocTemplateTagKindJSDocTypedefTagKindJSDocSeeTagKindJSDocPropertyTagKindJSDocSatisfiesTagKindJSDocImportTagKindSyntaxListKindJSTypeAliasDeclarationKindJSExportAssignmentKindCommonJSExportKindJSImportDeclarationKindNotEmittedStatementKindPartiallyEmittedExpressionKindCommaListExpressionKindSyntheticReferenceExpressionKindNotEmittedTypeElementKindCount" +const _Kind_name = "KindUnknownKindEndOfFileKindSingleLineCommentTriviaKindMultiLineCommentTriviaKindNewLineTriviaKindWhitespaceTriviaKindConflictMarkerTriviaKindNonTextFileMarkerTriviaKindNumericLiteralKindBigIntLiteralKindStringLiteralKindJsxTextKindJsxTextAllWhiteSpacesKindRegularExpressionLiteralKindNoSubstitutionTemplateLiteralKindTemplateHeadKindTemplateMiddleKindTemplateTailKindOpenBraceTokenKindCloseBraceTokenKindOpenParenTokenKindCloseParenTokenKindOpenBracketTokenKindCloseBracketTokenKindDotTokenKindDotDotDotTokenKindSemicolonTokenKindCommaTokenKindQuestionDotTokenKindLessThanTokenKindLessThanSlashTokenKindGreaterThanTokenKindLessThanEqualsTokenKindGreaterThanEqualsTokenKindEqualsEqualsTokenKindExclamationEqualsTokenKindEqualsEqualsEqualsTokenKindExclamationEqualsEqualsTokenKindEqualsGreaterThanTokenKindPlusTokenKindMinusTokenKindAsteriskTokenKindAsteriskAsteriskTokenKindSlashTokenKindPercentTokenKindPlusPlusTokenKindMinusMinusTokenKindLessThanLessThanTokenKindGreaterThanGreaterThanTokenKindGreaterThanGreaterThanGreaterThanTokenKindAmpersandTokenKindBarTokenKindCaretTokenKindExclamationTokenKindTildeTokenKindAmpersandAmpersandTokenKindBarBarTokenKindQuestionTokenKindColonTokenKindAtTokenKindQuestionQuestionTokenKindBacktickTokenKindHashTokenKindEqualsTokenKindPlusEqualsTokenKindMinusEqualsTokenKindAsteriskEqualsTokenKindAsteriskAsteriskEqualsTokenKindSlashEqualsTokenKindPercentEqualsTokenKindLessThanLessThanEqualsTokenKindGreaterThanGreaterThanEqualsTokenKindGreaterThanGreaterThanGreaterThanEqualsTokenKindAmpersandEqualsTokenKindBarEqualsTokenKindBarBarEqualsTokenKindAmpersandAmpersandEqualsTokenKindQuestionQuestionEqualsTokenKindCaretEqualsTokenKindIdentifierKindPrivateIdentifierKindJSDocCommentTextTokenKindBreakKeywordKindCaseKeywordKindCatchKeywordKindClassKeywordKindConstKeywordKindContinueKeywordKindDebuggerKeywordKindDefaultKeywordKindDeleteKeywordKindDoKeywordKindElseKeywordKindEnumKeywordKindExportKeywordKindExtendsKeywordKindFalseKeywordKindFinallyKeywordKindForKeywordKindFunctionKeywordKindIfKeywordKindImportKeywordKindInKeywordKindInstanceOfKeywordKindNewKeywordKindNullKeywordKindReturnKeywordKindSuperKeywordKindSwitchKeywordKindThisKeywordKindThrowKeywordKindTrueKeywordKindTryKeywordKindTypeOfKeywordKindVarKeywordKindVoidKeywordKindWhileKeywordKindWithKeywordKindImplementsKeywordKindInterfaceKeywordKindLetKeywordKindPackageKeywordKindPrivateKeywordKindProtectedKeywordKindPublicKeywordKindStaticKeywordKindYieldKeywordKindAbstractKeywordKindAccessorKeywordKindAsKeywordKindAssertsKeywordKindAssertKeywordKindAnyKeywordKindAsyncKeywordKindAwaitKeywordKindBooleanKeywordKindConstructorKeywordKindDeclareKeywordKindGetKeywordKindImmediateKeywordKindInferKeywordKindIntrinsicKeywordKindIsKeywordKindKeyOfKeywordKindModuleKeywordKindNamespaceKeywordKindNeverKeywordKindOutKeywordKindReadonlyKeywordKindRequireKeywordKindNumberKeywordKindObjectKeywordKindSatisfiesKeywordKindSetKeywordKindStringKeywordKindSymbolKeywordKindTypeKeywordKindUndefinedKeywordKindUniqueKeywordKindUnknownKeywordKindUsingKeywordKindFromKeywordKindGlobalKeywordKindBigIntKeywordKindOverrideKeywordKindOfKeywordKindDeferKeywordKindQualifiedNameKindComputedPropertyNameKindTypeParameterKindParameterKindDecoratorKindPropertySignatureKindPropertyDeclarationKindMethodSignatureKindMethodDeclarationKindClassStaticBlockDeclarationKindConstructorKindGetAccessorKindSetAccessorKindCallSignatureKindConstructSignatureKindIndexSignatureKindTypePredicateKindTypeReferenceKindFunctionTypeKindConstructorTypeKindTypeQueryKindTypeLiteralKindArrayTypeKindTupleTypeKindOptionalTypeKindRestTypeKindUnionTypeKindIntersectionTypeKindConditionalTypeKindInferTypeKindParenthesizedTypeKindThisTypeKindTypeOperatorKindIndexedAccessTypeKindMappedTypeKindLiteralTypeKindNamedTupleMemberKindTemplateLiteralTypeKindTemplateLiteralTypeSpanKindQuantifiedTypeKindImportTypeKindObjectBindingPatternKindArrayBindingPatternKindBindingElementKindArrayLiteralExpressionKindObjectLiteralExpressionKindPropertyAccessExpressionKindElementAccessExpressionKindCallExpressionKindNewExpressionKindTaggedTemplateExpressionKindTypeAssertionExpressionKindParenthesizedExpressionKindFunctionExpressionKindArrowFunctionKindDeleteExpressionKindTypeOfExpressionKindVoidExpressionKindAwaitExpressionKindPrefixUnaryExpressionKindPostfixUnaryExpressionKindBinaryExpressionKindConditionalExpressionKindTemplateExpressionKindYieldExpressionKindSpreadElementKindClassExpressionKindOmittedExpressionKindExpressionWithTypeArgumentsKindAsExpressionKindNonNullExpressionKindMetaPropertyKindSyntheticExpressionKindSatisfiesExpressionKindTemplateSpanKindSemicolonClassElementKindBlockKindEmptyStatementKindVariableStatementKindExpressionStatementKindIfStatementKindDoStatementKindWhileStatementKindForStatementKindForInStatementKindForOfStatementKindContinueStatementKindBreakStatementKindReturnStatementKindWithStatementKindSwitchStatementKindLabeledStatementKindThrowStatementKindTryStatementKindDebuggerStatementKindVariableDeclarationKindVariableDeclarationListKindFunctionDeclarationKindClassDeclarationKindInterfaceDeclarationKindTypeAliasDeclarationKindEnumDeclarationKindModuleDeclarationKindModuleBlockKindCaseBlockKindNamespaceExportDeclarationKindImportEqualsDeclarationKindImportDeclarationKindImportClauseKindNamespaceImportKindNamedImportsKindImportSpecifierKindExportAssignmentKindExportDeclarationKindNamedExportsKindNamespaceExportKindExportSpecifierKindMissingDeclarationKindExternalModuleReferenceKindJsxElementKindJsxSelfClosingElementKindJsxOpeningElementKindJsxClosingElementKindJsxFragmentKindJsxOpeningFragmentKindJsxClosingFragmentKindJsxAttributeKindJsxAttributesKindJsxSpreadAttributeKindJsxExpressionKindJsxNamespacedNameKindCaseClauseKindDefaultClauseKindHeritageClauseKindCatchClauseKindImportAttributesKindImportAttributeKindPropertyAssignmentKindShorthandPropertyAssignmentKindSpreadAssignmentKindEnumMemberKindSourceFileKindJSDocTypeExpressionKindJSDocNameReferenceKindJSDocMemberNameKindJSDocAllTypeKindJSDocNullableTypeKindJSDocNonNullableTypeKindJSDocOptionalTypeKindJSDocVariadicTypeKindJSDocKindJSDocTextKindJSDocTypeLiteralKindJSDocSignatureKindJSDocLinkKindJSDocLinkCodeKindJSDocLinkPlainKindJSDocTagKindJSDocAugmentsTagKindJSDocImplementsTagKindJSDocDeprecatedTagKindJSDocPublicTagKindJSDocPrivateTagKindJSDocProtectedTagKindJSDocReadonlyTagKindJSDocOverrideTagKindJSDocCallbackTagKindJSDocOverloadTagKindJSDocParameterTagKindJSDocReturnTagKindJSDocThisTagKindJSDocTypeTagKindJSDocTemplateTagKindJSDocTypedefTagKindJSDocSeeTagKindJSDocPropertyTagKindJSDocSatisfiesTagKindJSDocImportTagKindSyntaxListKindJSTypeAliasDeclarationKindJSExportAssignmentKindCommonJSExportKindJSImportDeclarationKindNotEmittedStatementKindPartiallyEmittedExpressionKindCommaListExpressionKindSyntheticReferenceExpressionKindNotEmittedTypeElementKindCount" -var _Kind_index = [...]uint16{0, 11, 24, 51, 77, 94, 114, 138, 165, 183, 200, 217, 228, 253, 281, 314, 330, 348, 364, 382, 401, 419, 438, 458, 479, 491, 509, 527, 541, 561, 578, 600, 620, 643, 669, 690, 716, 743, 775, 801, 814, 828, 845, 870, 884, 900, 917, 936, 961, 992, 1034, 1052, 1064, 1078, 1098, 1112, 1139, 1154, 1171, 1185, 1196, 1221, 1238, 1251, 1266, 1285, 1305, 1328, 1359, 1379, 1401, 1432, 1469, 1517, 1541, 1559, 1580, 1613, 1644, 1664, 1678, 1699, 1724, 1740, 1755, 1771, 1787, 1803, 1822, 1841, 1859, 1876, 1889, 1904, 1919, 1936, 1954, 1970, 1988, 2002, 2021, 2034, 2051, 2064, 2085, 2099, 2114, 2131, 2147, 2164, 2179, 2195, 2210, 2224, 2241, 2255, 2270, 2286, 2301, 2322, 2342, 2356, 2374, 2392, 2412, 2429, 2446, 2462, 2481, 2500, 2513, 2531, 2548, 2562, 2578, 2594, 2612, 2634, 2652, 2666, 2686, 2702, 2722, 2735, 2751, 2768, 2788, 2804, 2818, 2837, 2855, 2872, 2889, 2909, 2923, 2940, 2957, 2972, 2992, 3009, 3027, 3043, 3058, 3075, 3092, 3111, 3124, 3140, 3157, 3181, 3198, 3211, 3224, 3245, 3268, 3287, 3308, 3339, 3354, 3369, 3384, 3401, 3423, 3441, 3458, 3475, 3491, 3510, 3523, 3538, 3551, 3564, 3580, 3592, 3605, 3625, 3644, 3657, 3678, 3690, 3706, 3727, 3741, 3756, 3776, 3799, 3826, 3840, 3864, 3887, 3905, 3931, 3958, 3986, 4013, 4031, 4048, 4076, 4103, 4130, 4152, 4169, 4189, 4209, 4227, 4246, 4271, 4297, 4317, 4342, 4364, 4383, 4400, 4419, 4440, 4471, 4487, 4508, 4524, 4547, 4570, 4586, 4611, 4620, 4638, 4659, 4682, 4697, 4712, 4730, 4746, 4764, 4782, 4803, 4821, 4840, 4857, 4876, 4896, 4914, 4930, 4951, 4974, 5001, 5024, 5044, 5068, 5092, 5111, 5132, 5147, 5160, 5190, 5217, 5238, 5254, 5273, 5289, 5308, 5328, 5349, 5365, 5384, 5403, 5425, 5452, 5466, 5491, 5512, 5533, 5548, 5570, 5592, 5608, 5625, 5647, 5664, 5685, 5699, 5716, 5734, 5749, 5769, 5788, 5810, 5841, 5861, 5875, 5889, 5912, 5934, 5953, 5969, 5990, 6014, 6035, 6056, 6065, 6078, 6098, 6116, 6129, 6146, 6164, 6176, 6196, 6218, 6240, 6258, 6277, 6298, 6318, 6338, 6358, 6378, 6399, 6417, 6433, 6449, 6469, 6488, 6503, 6523, 6544, 6562, 6576, 6602, 6624, 6642, 6665, 6688, 6718, 6741, 6773, 6798, 6807} +var _Kind_index = [...]uint16{0, 11, 24, 51, 77, 94, 114, 138, 165, 183, 200, 217, 228, 253, 281, 314, 330, 348, 364, 382, 401, 419, 438, 458, 479, 491, 509, 527, 541, 561, 578, 600, 620, 643, 669, 690, 716, 743, 775, 801, 814, 828, 845, 870, 884, 900, 917, 936, 961, 992, 1034, 1052, 1064, 1078, 1098, 1112, 1139, 1154, 1171, 1185, 1196, 1221, 1238, 1251, 1266, 1285, 1305, 1328, 1359, 1379, 1401, 1432, 1469, 1517, 1541, 1559, 1580, 1613, 1644, 1664, 1678, 1699, 1724, 1740, 1755, 1771, 1787, 1803, 1822, 1841, 1859, 1876, 1889, 1904, 1919, 1936, 1954, 1970, 1988, 2002, 2021, 2034, 2051, 2064, 2085, 2099, 2114, 2131, 2147, 2164, 2179, 2195, 2210, 2224, 2241, 2255, 2270, 2286, 2301, 2322, 2342, 2356, 2374, 2392, 2412, 2429, 2446, 2462, 2481, 2500, 2513, 2531, 2548, 2562, 2578, 2594, 2612, 2634, 2652, 2666, 2686, 2702, 2722, 2735, 2751, 2768, 2788, 2804, 2818, 2837, 2855, 2872, 2889, 2909, 2923, 2940, 2957, 2972, 2992, 3009, 3027, 3043, 3058, 3075, 3092, 3111, 3124, 3140, 3157, 3181, 3198, 3211, 3224, 3245, 3268, 3287, 3308, 3339, 3354, 3369, 3384, 3401, 3423, 3441, 3458, 3475, 3491, 3510, 3523, 3538, 3551, 3564, 3580, 3592, 3605, 3625, 3644, 3657, 3678, 3690, 3706, 3727, 3741, 3756, 3776, 3799, 3826, 3844, 3858, 3882, 3905, 3923, 3949, 3976, 4004, 4031, 4049, 4066, 4094, 4121, 4148, 4170, 4187, 4207, 4227, 4245, 4264, 4289, 4315, 4335, 4360, 4382, 4401, 4418, 4437, 4458, 4489, 4505, 4526, 4542, 4565, 4588, 4604, 4629, 4638, 4656, 4677, 4700, 4715, 4730, 4748, 4764, 4782, 4800, 4821, 4839, 4858, 4875, 4894, 4914, 4932, 4948, 4969, 4992, 5019, 5042, 5062, 5086, 5110, 5129, 5150, 5165, 5178, 5208, 5235, 5256, 5272, 5291, 5307, 5326, 5346, 5367, 5383, 5402, 5421, 5443, 5470, 5484, 5509, 5530, 5551, 5566, 5588, 5610, 5626, 5643, 5665, 5682, 5703, 5717, 5734, 5752, 5767, 5787, 5806, 5828, 5859, 5879, 5893, 5907, 5930, 5952, 5971, 5987, 6008, 6032, 6053, 6074, 6083, 6096, 6116, 6134, 6147, 6164, 6182, 6194, 6214, 6236, 6258, 6276, 6295, 6316, 6336, 6356, 6376, 6396, 6417, 6435, 6451, 6467, 6487, 6506, 6521, 6541, 6562, 6580, 6594, 6620, 6642, 6660, 6683, 6706, 6736, 6759, 6791, 6816, 6825} func (i Kind) String() string { idx := int(i) - 0 diff --git a/internal/ast/precedence.go b/internal/ast/precedence.go index 9acf84a78f..b3113f62ef 100644 --- a/internal/ast/precedence.go +++ b/internal/ast/precedence.go @@ -655,7 +655,8 @@ const ( // Gets the precedence of a TypeNode func GetTypeNodePrecedence(n *TypeNode) TypePrecedence { switch n.Kind { - case KindConditionalType: + case KindConditionalType, + KindQuantifiedType: return TypePrecedenceConditional case KindJSDocOptionalType, KindJSDocVariadicType: return TypePrecedenceJSDoc diff --git a/internal/binder/binder.go b/internal/binder/binder.go index f7339d9870..341beb946b 100644 --- a/internal/binder/binder.go +++ b/internal/binder/binder.go @@ -447,7 +447,8 @@ func (b *Binder) declareSymbolAndAddToSymbolTable(node *ast.Node, symbolFlags as case ast.KindFunctionType, ast.KindConstructorType, ast.KindCallSignature, ast.KindConstructSignature, ast.KindIndexSignature, ast.KindMethodDeclaration, ast.KindMethodSignature, ast.KindConstructor, ast.KindGetAccessor, ast.KindSetAccessor, ast.KindFunctionDeclaration, ast.KindFunctionExpression, ast.KindArrowFunction, - ast.KindClassStaticBlockDeclaration, ast.KindTypeAliasDeclaration, ast.KindJSTypeAliasDeclaration, ast.KindMappedType: + ast.KindClassStaticBlockDeclaration, ast.KindTypeAliasDeclaration, ast.KindJSTypeAliasDeclaration, ast.KindMappedType, + ast.KindQuantifiedType: return b.declareSymbol(ast.GetLocals(b.container), nil /*parent*/, node, symbolFlags, symbolExcludes) } panic("Unhandled case in declareSymbolAndAddToSymbolTable") @@ -2467,7 +2468,7 @@ func GetContainerFlags(node *ast.Node) ContainerFlags { return ContainerFlagsIsContainer case ast.KindInterfaceDeclaration: return ContainerFlagsIsContainer | ContainerFlagsIsInterface - case ast.KindModuleDeclaration, ast.KindTypeAliasDeclaration, ast.KindJSTypeAliasDeclaration, ast.KindMappedType, ast.KindIndexSignature: + case ast.KindModuleDeclaration, ast.KindTypeAliasDeclaration, ast.KindJSTypeAliasDeclaration, ast.KindMappedType, ast.KindIndexSignature, ast.KindQuantifiedType: return ContainerFlagsIsContainer | ContainerFlagsHasLocals case ast.KindSourceFile: return ContainerFlagsIsContainer | ContainerFlagsIsControlFlowContainer | ContainerFlagsHasLocals diff --git a/internal/checker/checker.go b/internal/checker/checker.go index f2a212a060..fc0b358c6b 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -44,8 +44,9 @@ const ( CheckModeRestBindingElement CheckMode = 1 << 5 // Checking a type that is going to be used to determine the type of a rest binding element // e.g. in `const { a, ...rest } = foo`, when checking the type of `foo` to determine the type of `rest`, // we need to preserve generic types instead of substituting them for constraints - CheckModeTypeOnly CheckMode = 1 << 6 // Called from getTypeOfExpression, diagnostics may be omitted - CheckModeForceTuple CheckMode = 1 << 7 + CheckModeTypeOnly CheckMode = 1 << 6 // Called from getTypeOfExpression, diagnostics may be omitted + CheckModeForceTuple CheckMode = 1 << 7 + CheckModeQuantifiedContextual CheckMode = 1 << 8 ) type TypeSystemEntity any @@ -7246,6 +7247,9 @@ func (c *Checker) reportObjectPossiblyNullOrUndefinedError(node *ast.Node, facts } func (c *Checker) checkExpressionWithContextualType(node *ast.Node, contextualType *Type, inferenceContext *InferenceContext, checkMode CheckMode) *Type { + if contextualType.flags&TypeFlagsQuantified != 0 { + return c.checkExpressionExWithContextualType(node, checkMode, contextualType, inferenceContext) + } contextNode := c.getContextNode(node) c.pushContextualType(contextNode, contextualType, false /*isCache*/) c.pushInferenceContext(contextNode, inferenceContext) @@ -7319,6 +7323,63 @@ func (c *Checker) checkExpression(node *ast.Node) *Type { } func (c *Checker) checkExpressionEx(node *ast.Node, checkMode CheckMode) *Type { + return c.checkExpressionExWithContextualType(node, checkMode, nil, nil) +} + +// we now have too many checkExpression* functions and it's a bit of a spagetti so maybe there is a better way to do this +// but it's done this way to reduce the number of locations where a change has to be made for quantified types +func (c *Checker) checkExpressionExWithContextualType(node *ast.Node, parentCheckMode CheckMode, contextualType *Type, parentInferenceContext *InferenceContext) *Type { + if node.Kind == ast.KindIdentifier { // to avoid recursion in some jsx test cases TODO: come up with a better fix + return c.checkExpressionExWorker(node, parentCheckMode) + } + if contextualType == nil { + contextualType = c.getApparentTypeOfContextualType(node, ContextFlagsNone) + } + if parentInferenceContext == nil { + parentInferenceContext = c.getInferenceContext(node) + } + isAlreadyContextuallyChecking := c.contextualInfos != nil && core.Some(c.contextualInfos, func(info ContextualInfo) bool { return info.node == node }) + if contextualType == nil || contextualType.flags&TypeFlagsQuantified == 0 || isAlreadyContextuallyChecking { + return c.checkExpressionExWorker(node, parentCheckMode) + } + baseType := contextualType.AsQuantifiedType().baseType + if parentInferenceContext != nil { + baseType = c.instantiateType(baseType, parentInferenceContext.nonFixingMapper) + } + typeParameters := core.Map(contextualType.AsQuantifiedType().typeParameters, func(tp *TypeParameter) *Type { return tp.AsType() }) + + // context sensitive + // TODO: this is not needed if the node is not context sensitive + inferenceContext := c.newInferenceContext(typeParameters, nil, InferenceFlagsNone, nil) + if parentInferenceContext != nil { + // probably a bad way to comvine inference contexts but works + inferenceContext.nonFixingMapper = c.combineTypeMappers(inferenceContext.nonFixingMapper, parentInferenceContext.nonFixingMapper) + inferenceContext.mapper = c.combineTypeMappers(inferenceContext.mapper, parentInferenceContext.mapper) + } + t := c.checkExpressionWithContextualType(node, baseType, inferenceContext, parentCheckMode|CheckModeSkipContextSensitive|CheckModeQuantifiedContextual) + if t.objectFlags&ObjectFlagsNonInferrableType != 0 && parentCheckMode&CheckModeSkipContextSensitive != 0 { + return t + } + c.inferTypes(inferenceContext.inferences, t, baseType, InferencePriorityNone, false) + typeArguments := c.instantiateTypes(typeParameters, inferenceContext.nonFixingMapper) + + // normal + t = c.checkExpressionWithContextualType(node, baseType, inferenceContext, CheckModeNormal|CheckModeQuantifiedContextual) + c.inferTypes(inferenceContext.inferences, t, baseType, InferencePriorityNone, false) + typeArguments = c.instantiateTypes(typeParameters, inferenceContext.mapper) + + // final + baseType = c.instantiateType(baseType, newTypeMapper(typeParameters, typeArguments)) + t = c.checkExpressionWithContextualType(node, baseType, core.IfElse(parentInferenceContext != nil, parentInferenceContext, nil), CheckModeNormal|CheckModeQuantifiedContextual) + + if !c.checkTypeRelatedToAndOptionallyElaborate(t, baseType, c.assignableRelation, node, node, nil, nil) { + return c.errorType // to avoid showing errors in parent TODO: maybe there is a better way to do this + } + + return t +} + +func (c *Checker) checkExpressionExWorker(node *ast.Node, checkMode CheckMode) *Type { saveCurrentNode := c.currentNode c.currentNode = node c.instantiationCount = 0 @@ -9937,12 +9998,12 @@ func (c *Checker) checkFunctionExpressionOrObjectLiteralMethod(node *ast.Node, c func (c *Checker) contextuallyCheckFunctionExpressionOrObjectLiteralMethod(node *ast.Node, checkMode CheckMode) { links := c.nodeLinks.Get(node) // Check if function expression is contextually typed and assign parameter types if so. - if links.flags&NodeCheckFlagsContextChecked == 0 { + if links.flags&NodeCheckFlagsContextChecked == 0 || checkMode&CheckModeQuantifiedContextual != 0 { contextualSignature := c.getContextualSignature(node) // If a type check is started at a function expression that is an argument of a function call, obtaining the // contextual type may recursively get back to here during overload resolution of the call. If so, we will have // already assigned contextual types. - if links.flags&NodeCheckFlagsContextChecked == 0 { + if links.flags&NodeCheckFlagsContextChecked == 0 || checkMode&CheckModeQuantifiedContextual != 0 { links.flags |= NodeCheckFlagsContextChecked signature := core.FirstOrNil(c.getSignaturesOfType(c.getTypeOfSymbol(c.getSymbolOfDeclaration(node)), SignatureKindCall)) if signature == nil { @@ -16821,7 +16882,7 @@ func (c *Checker) getDeclaredTypeOfClassOrInterface(symbol *ast.Symbol) *Type { t := c.newObjectType(kind, symbol) links.declaredType = t outerTypeParameters := c.getOuterTypeParametersOfClassOrInterface(symbol) - typeParameters := c.appendLocalTypeParametersOfClassOrInterfaceOrTypeAlias(outerTypeParameters, symbol) + typeParameters := c.appendLocalTypeParametersOfClassOrInterfaceOrTypeAliasOrQuantifiedType(outerTypeParameters, symbol) // A class or interface is generic if it has type parameters or a "this" type. We always give classes a "this" type // because it is not feasible to analyze all members to determine if the "this" type escapes the class (in particular, // property types inferred from initializers and method return types inferred from return statements are very hard @@ -20877,7 +20938,7 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name s // If we merged instantiations of a generic type, we replicate the symbol parent resetting behavior we used // to do when we recorded multiple distinct symbols so that we still get, eg, `Array.length` printed // back and not `Array.length` when we're looking at a `.length` access on a `string[] | number[]` - mergedInstantiations = singleProp.Parent != nil && len(c.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(singleProp.Parent)) != 0 + mergedInstantiations = singleProp.Parent != nil && len(c.getLocalTypeParametersOfClassOrInterfaceOrTypeAliasOrQuantifiedType(singleProp.Parent)) != 0 } else { if propSet.Size() == 0 { propSet.Add(singleProp) @@ -21606,6 +21667,17 @@ func (c *Checker) instantiateTypeWorker(t *Type, m *TypeMapper, alias *TypeAlias switch { case flags&TypeFlagsTypeParameter != 0: return m.Map(t) + case flags&TypeFlagsQuantified != 0: + return c.newQuantifiedType( + t.AsQuantifiedType().typeParameters, + // TODO: the following does not work figure out a way to do it + /*core.Map(t.AsQuantifiedType().typeParameters, func(tp *TypeParameter) *TypeParameter { + newTp := c.cloneTypeParameter(tp.AsType()) + newTp.AsTypeParameter().constraint = c.instantiateType(newTp.AsTypeParameter().constraint, m) + return newTp.AsTypeParameter() + }),*/ + c.instantiateType(t.AsQuantifiedType().baseType, m), + ) case flags&TypeFlagsObject != 0: objectFlags := t.objectFlags if objectFlags&(ObjectFlagsReference|ObjectFlagsAnonymous|ObjectFlagsMapped) != 0 { @@ -22277,6 +22349,8 @@ func (c *Checker) getTypeFromTypeNodeWorker(node *ast.Node) *Type { return c.getTypeFromInferTypeNode(node) case ast.KindImportType: return c.getTypeFromImportTypeNode(node) + case ast.KindQuantifiedType: + return c.getTypeFromQuantifiedTypeNode(node) default: return c.errorType } @@ -23043,7 +23117,7 @@ func (c *Checker) getAliasSymbolForTypeNode(node *ast.Node) *ast.Symbol { func (c *Checker) getTypeArgumentsForAliasSymbol(symbol *ast.Symbol) []*Type { if symbol != nil { - return c.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) + return c.getLocalTypeParametersOfClassOrInterfaceOrTypeAliasOrQuantifiedType(symbol) } return nil } @@ -23078,7 +23152,7 @@ func (c *Checker) getOuterTypeParameters(node *ast.Node, includeThisTypes bool) case ast.KindClassDeclaration, ast.KindClassExpression, ast.KindInterfaceDeclaration, ast.KindCallSignature, ast.KindConstructSignature, ast.KindMethodSignature, ast.KindFunctionType, ast.KindConstructorType, ast.KindFunctionDeclaration, ast.KindMethodDeclaration, ast.KindFunctionExpression, ast.KindArrowFunction, ast.KindTypeAliasDeclaration, ast.KindJSTypeAliasDeclaration, ast.KindMappedType, - ast.KindConditionalType: + ast.KindConditionalType, ast.KindQuantifiedType: outerTypeParameters := c.getOuterTypeParameters(node, includeThisTypes) if (kind == ast.KindFunctionExpression || kind == ast.KindArrowFunction || ast.IsObjectLiteralMethod(node)) && c.isContextSensitive(node) { signature := core.FirstOrNil(c.getSignaturesOfType(c.getTypeOfSymbol(c.getSymbolOfDeclaration(node)), SignatureKindCall)) @@ -23116,14 +23190,14 @@ func (c *Checker) getInferTypeParameters(node *ast.Node) []*Type { } // The local type parameters are the combined set of type parameters from all declarations of the class, -// interface, or type alias. -func (c *Checker) getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol *ast.Symbol) []*Type { - return c.appendLocalTypeParametersOfClassOrInterfaceOrTypeAlias(nil, symbol) +// interface, type alias or quantified type +func (c *Checker) getLocalTypeParametersOfClassOrInterfaceOrTypeAliasOrQuantifiedType(symbol *ast.Symbol) []*Type { + return c.appendLocalTypeParametersOfClassOrInterfaceOrTypeAliasOrQuantifiedType(nil, symbol) } -func (c *Checker) appendLocalTypeParametersOfClassOrInterfaceOrTypeAlias(types []*Type, symbol *ast.Symbol) []*Type { +func (c *Checker) appendLocalTypeParametersOfClassOrInterfaceOrTypeAliasOrQuantifiedType(types []*Type, symbol *ast.Symbol) []*Type { for _, node := range symbol.Declarations { - if ast.NodeKindIs(node, ast.KindInterfaceDeclaration, ast.KindClassDeclaration, ast.KindClassExpression) || isTypeAlias(node) { + if ast.NodeKindIs(node, ast.KindInterfaceDeclaration, ast.KindClassDeclaration, ast.KindClassExpression, ast.KindQuantifiedType) || isTypeAlias(node) { types = c.appendTypeParameters(types, node.TypeParameters()) } } @@ -23160,7 +23234,7 @@ func (c *Checker) getDeclaredTypeOfTypeAlias(symbol *ast.Symbol) *Type { typeNode := declaration.Type() t := c.getTypeFromTypeNode(typeNode) if c.popTypeResolution() { - typeParameters := c.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) + typeParameters := c.getLocalTypeParametersOfClassOrInterfaceOrTypeAliasOrQuantifiedType(symbol) if len(typeParameters) != 0 { // Initialize the instantiation cache for generic type aliases. The declared type corresponds to // an instantiation of the type alias with the type parameters supplied as type arguments. @@ -23954,6 +24028,19 @@ func (c *Checker) getTypeFromImportTypeNode(node *ast.Node) *Type { return links.resolvedType } +func (c *Checker) getTypeFromQuantifiedTypeNode(node *ast.Node) *Type { + links := c.typeNodeLinks.Get(node) + if links.resolvedType == nil { + links.resolvedType = c.newQuantifiedType( + core.Map(node.AsQuantifiedTypeNode().TypeParameters.Nodes, func(typeParameterNode *ast.Node) *TypeParameter { + return c.getDeclaredTypeOfTypeParameter(typeParameterNode.Symbol()).AsTypeParameter() + }), + c.getTypeFromTypeNode(node.AsQuantifiedTypeNode().BaseType), + ) + } + return links.resolvedType +} + func (c *Checker) getIdentifierChain(node *ast.Node) []*ast.Node { if ast.IsIdentifier(node) { return []*ast.Node{node} @@ -24545,6 +24632,13 @@ func (c *Checker) newSubstitutionType(baseType *Type, constraint *Type) *Type { return c.newType(TypeFlagsSubstitution, ObjectFlagsNone, data) } +func (c *Checker) newQuantifiedType(typeParamters []*TypeParameter, baseType *Type) *Type { + data := &QuantifiedType{} + data.typeParameters = typeParamters + data.baseType = baseType + return c.newType(TypeFlagsQuantified, ObjectFlagsNone, data) +} + func (c *Checker) newSignature(flags SignatureFlags, declaration *ast.Node, typeParameters []*Type, thisParameter *ast.Symbol, parameters []*ast.Symbol, resolvedReturnType *Type, resolvedTypePredicate *TypePredicate, minArgumentCount int) *Signature { sig := c.signaturePool.New() sig.flags = flags @@ -26681,6 +26775,11 @@ func (c *Checker) getBaseConstraintOrType(t *Type) *Type { } func (c *Checker) getBaseConstraintOfType(t *Type) *Type { + if t.flags&TypeFlagsQuantified != 0 { + return c.getBaseConstraintOfType( + t.AsQuantifiedType().baseType, + ) + } if t.flags&(TypeFlagsInstantiableNonPrimitive|TypeFlagsUnionOrIntersection|TypeFlagsTemplateLiteral|TypeFlagsStringMapping) != 0 || c.isGenericTupleType(t) { constraint := c.getResolvedBaseConstraint(t, nil) if constraint != c.noConstraintType && constraint != c.circularConstraintType { @@ -29674,6 +29773,9 @@ func (c *Checker) getApparentTypeOfContextualType(node *ast.Node, contextFlags C instantiatedType := c.instantiateContextualType(contextualType, node, contextFlags) if instantiatedType != nil && !(contextFlags&ContextFlagsNoConstraints != 0 && instantiatedType.flags&TypeFlagsTypeVariable != 0) { apparentType := c.mapTypeEx(instantiatedType, func(t *Type) *Type { + if t.flags&TypeFlagsQuantified != 0 { + return t + } if t.objectFlags&ObjectFlagsMapped != 0 { return t } diff --git a/internal/checker/exports.go b/internal/checker/exports.go index 332a72569e..4cbbc1f6ed 100644 --- a/internal/checker/exports.go +++ b/internal/checker/exports.go @@ -135,7 +135,7 @@ func (c *Checker) HasEffectiveRestParameter(signature *Signature) bool { } func (c *Checker) GetLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol *ast.Symbol) []*Type { - return c.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) + return c.getLocalTypeParametersOfClassOrInterfaceOrTypeAliasOrQuantifiedType(symbol) } func (c *Checker) GetContextualTypeForObjectLiteralElement(element *ast.Node, contextFlags ContextFlags) *Type { diff --git a/internal/checker/jsx.go b/internal/checker/jsx.go index 9bf61948b9..f6f18c85bd 100644 --- a/internal/checker/jsx.go +++ b/internal/checker/jsx.go @@ -968,7 +968,7 @@ func (c *Checker) getJsxPropsTypeFromClassType(sig *Signature, context *ast.Node apparentAttributesType := attributesType intrinsicClassAttribs := c.getJsxType(JsxNames.IntrinsicClassAttributes, context) if !c.isErrorType(intrinsicClassAttribs) { - typeParams := c.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol) + typeParams := c.getLocalTypeParametersOfClassOrInterfaceOrTypeAliasOrQuantifiedType(intrinsicClassAttribs.symbol) hostClassType := c.getReturnTypeOfSignature(sig) var libraryManagedAttributeType *Type if typeParams != nil { diff --git a/internal/checker/nodebuilderimpl.go b/internal/checker/nodebuilderimpl.go index 1fb4c35794..8d0bdc1fa9 100644 --- a/internal/checker/nodebuilderimpl.go +++ b/internal/checker/nodebuilderimpl.go @@ -897,7 +897,7 @@ func (b *NodeBuilderImpl) getNameOfSymbolAsWritten(symbol *ast.Symbol) string { func (b *NodeBuilderImpl) getTypeParametersOfClassOrInterface(symbol *ast.Symbol) []*Type { result := make([]*Type, 0) result = append(result, b.ch.getOuterTypeParametersOfClassOrInterface(symbol)...) - result = append(result, b.ch.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol)...) + result = append(result, b.ch.getLocalTypeParametersOfClassOrInterfaceOrTypeAliasOrQuantifiedType(symbol)...) return result } @@ -1518,7 +1518,7 @@ func (b *NodeBuilderImpl) typeParametersToTypeParameterDeclarations(symbol *ast. targetSymbol := b.ch.getTargetSymbol(symbol) if targetSymbol.Flags&(ast.SymbolFlagsClass|ast.SymbolFlagsInterface|ast.SymbolFlagsAlias) != 0 { var results []*ast.Node - params := b.ch.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) + params := b.ch.getLocalTypeParametersOfClassOrInterfaceOrTypeAliasOrQuantifiedType(symbol) for _, param := range params { results = append(results, b.typeParameterToDeclaration(param)) } @@ -3091,6 +3091,16 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { return typeNode } } + if t.flags&TypeFlagsQuantified != 0 { + return b.f.NewQuantifiedTypeNode( + b.f.NewNodeList( + core.Map(t.AsQuantifiedType().typeParameters, func(typeParamter *TypeParameter) *ast.Node { + return b.typeParameterToDeclaration(typeParamter.AsType()) + }), + ), + b.typeToTypeNode(t.AsQuantifiedType().baseType), + ) + } panic("Should be unreachable.") } diff --git a/internal/checker/relater.go b/internal/checker/relater.go index bf65552c7f..d75c13cdf2 100644 --- a/internal/checker/relater.go +++ b/internal/checker/relater.go @@ -168,6 +168,31 @@ func (c *Checker) areTypesComparable(type1 *Type, type2 *Type) bool { } func (c *Checker) isTypeRelatedTo(source *Type, target *Type, relation *Relation) bool { + if target.flags&TypeFlagsQuantified != 0 { + if source.flags&TypeFlagsQuantified != 0 { + return source == target + } + baseType := target.AsQuantifiedType().baseType + typeParameters := core.Map(target.AsQuantifiedType().typeParameters, func(t *TypeParameter) *Type { return t.AsType() }) + + if source.flags&TypeFlagsUnion == 0 { + inferenceContext := c.newInferenceContext(typeParameters, nil, InferenceFlagsNone, nil) + c.inferTypes(inferenceContext.inferences, source, baseType, InferencePriorityNone, false) + return c.isTypeRelatedTo(source, c.instantiateType(baseType, inferenceContext.mapper), relation) + } + + for _, sourceMember := range source.AsUnionType().types { + inferenceContext := c.newInferenceContext(typeParameters, nil, InferenceFlagsNone, nil) + c.inferTypes(inferenceContext.inferences, sourceMember, baseType, InferencePriorityNone, false) + result := c.isTypeRelatedTo(sourceMember, c.instantiateType(baseType, inferenceContext.mapper), relation) + if result { + continue + } + return result + } + + return true + } if isFreshLiteralType(source) { source = source.AsLiteralType().regularType } @@ -2553,6 +2578,32 @@ func (r *Relater) isRelatedTo(source *Type, target *Type, recursionFlags Recursi } func (r *Relater) isRelatedToEx(originalSource *Type, originalTarget *Type, recursionFlags RecursionFlags, reportErrors bool, headMessage *diagnostics.Message, intersectionState IntersectionState) Ternary { + if originalTarget.flags&TypeFlagsQuantified != 0 { + if originalSource.flags&TypeFlagsQuantified != 0 && originalSource == originalTarget { + return TernaryTrue + } + baseType := originalTarget.AsQuantifiedType().baseType + typeParameters := core.Map(originalTarget.AsQuantifiedType().typeParameters, func(t *TypeParameter) *Type { return t.AsType() }) + + if originalSource.flags&TypeFlagsUnion == 0 { + inferenceContext := r.c.newInferenceContext(typeParameters, nil, InferenceFlagsNone, nil) + r.c.inferTypes(inferenceContext.inferences, originalSource, baseType, InferencePriorityNone, false) + return r.isRelatedToEx(originalSource, r.c.instantiateType(baseType, inferenceContext.mapper), recursionFlags, reportErrors, headMessage, intersectionState) + } + + for _, originalSourceMember := range originalSource.AsUnionType().types { + inferenceContext := r.c.newInferenceContext(typeParameters, nil, InferenceFlagsNone, nil) + r.c.inferTypes(inferenceContext.inferences, originalSourceMember, baseType, InferencePriorityNone, false) + result := r.isRelatedToEx(originalSourceMember, r.c.instantiateType(baseType, inferenceContext.mapper), recursionFlags, reportErrors, headMessage, intersectionState) + if result == TernaryTrue { + continue + } + return result + } + + return TernaryTrue + } + if originalSource == originalTarget { return TernaryTrue } diff --git a/internal/checker/types.go b/internal/checker/types.go index 3e2aafbd4c..b872bd7b51 100644 --- a/internal/checker/types.go +++ b/internal/checker/types.go @@ -379,7 +379,7 @@ type SignatureLinks struct { decoratorSignature *Signature // Signature for decorator as if invoked by the runtime } -type TypeFlags uint32 +type TypeFlags uint64 // Note that for types of different kinds, the numeric values of TypeFlags determine the order // computed by the CompareTypes function and therefore the order of constituent types in union types. @@ -421,6 +421,7 @@ const ( TypeFlagsReserved1 TypeFlags = 1 << 29 // Used by union/intersection type construction TypeFlagsReserved2 TypeFlags = 1 << 30 // Used by union/intersection type construction TypeFlagsReserved3 TypeFlags = 1 << 31 + TypeFlagsQuantified TypeFlags = 1 << 32 TypeFlagsAnyOrUnknown = TypeFlagsAny | TypeFlagsUnknown TypeFlagsNullable = TypeFlagsUndefined | TypeFlagsNull @@ -445,7 +446,7 @@ const ( TypeFlagsUnionOrIntersection = TypeFlagsUnion | TypeFlagsIntersection TypeFlagsStructuredType = TypeFlagsObject | TypeFlagsUnion | TypeFlagsIntersection TypeFlagsTypeVariable = TypeFlagsTypeParameter | TypeFlagsIndexedAccess - TypeFlagsInstantiableNonPrimitive = TypeFlagsTypeVariable | TypeFlagsConditional | TypeFlagsSubstitution + TypeFlagsInstantiableNonPrimitive = TypeFlagsTypeVariable | TypeFlagsConditional | TypeFlagsSubstitution | TypeFlagsQuantified TypeFlagsInstantiablePrimitive = TypeFlagsIndex | TypeFlagsTemplateLiteral | TypeFlagsStringMapping TypeFlagsInstantiable = TypeFlagsInstantiableNonPrimitive | TypeFlagsInstantiablePrimitive TypeFlagsStructuredOrInstantiable = TypeFlagsStructuredType | TypeFlagsInstantiable @@ -594,6 +595,7 @@ func (t *Type) AsTemplateLiteralType() *TemplateLiteralType { return t.data.(*Te func (t *Type) AsStringMappingType() *StringMappingType { return t.data.(*StringMappingType) } func (t *Type) AsSubstitutionType() *SubstitutionType { return t.data.(*SubstitutionType) } func (t *Type) AsConditionalType() *ConditionalType { return t.data.(*ConditionalType) } +func (t *Type) AsQuantifiedType() *QuantifiedType { return t.data.(*QuantifiedType) } // Casts for embedded struct types @@ -1100,6 +1102,12 @@ type ConditionalType struct { combinedMapper *TypeMapper } +type QuantifiedType struct { + ConstrainedType + typeParameters []*TypeParameter + baseType *Type +} + // SignatureFlags type SignatureFlags uint32 diff --git a/internal/parser/parser.go b/internal/parser/parser.go index 00436c0a1b..8b982b40b7 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -2480,6 +2480,21 @@ func (p *Parser) parseType() *ast.TypeNode { saveContextFlags := p.contextFlags p.setContextFlags(ast.NodeFlagsTypeExcludesFlags, false) var typeNode *ast.TypeNode + if p.token == ast.KindLessThanToken { + state := p.mark() + p.parseFunctionOrConstructorType() + couldParseFunctionType := len(p.diagnostics) == state.diagnosticsLen + // TODO: see if there's a more standard way to do "try" parse + p.rewind(state) + if !couldParseFunctionType { + pos := p.nodePos() + typeParameters := p.parseTypeParameters() + baseType := p.parseType() + typeNode = p.finishNode(p.factory.NewQuantifiedTypeNode(typeParameters, baseType), pos) + p.contextFlags = saveContextFlags + return typeNode + } + } if p.isStartOfFunctionTypeOrConstructorType() { typeNode = p.parseFunctionOrConstructorType() } else { diff --git a/internal/printer/printer.go b/internal/printer/printer.go index fec95a7ab1..b21646cfc4 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -2182,6 +2182,15 @@ func (p *Printer) emitImportTypeNode(node *ast.ImportTypeNode) { p.exitNode(node.AsNode(), state) } +func (p *Printer) emitQuantifiedTypeNpde(node *ast.QuantifiedTypeNode) { + state := p.enterNode(node.AsNode()) + p.emitTypeParameters(node.AsNode(), node.TypeParameters) + p.writeSpace() + // TODO: print parenthesis if BaseType is a function + p.emitTypeNode(node.BaseType, ast.TypePrecedenceConditional) + p.exitNode(node.AsNode(), state) +} + // emits a Type node in the `extends` clause of a ConditionalType func (p *Printer) emitTypeNodeInExtends(node *ast.TypeNode) { savedInExtends := p.inExtends @@ -2281,6 +2290,8 @@ func (p *Printer) emitTypeNode(node *ast.TypeNode, precedence ast.TypePrecedence p.emitTemplateTypeSpan(node.AsTemplateLiteralTypeSpan()) case ast.KindImportType: p.emitImportTypeNode(node.AsImportTypeNode()) + case ast.KindQuantifiedType: + p.emitQuantifiedTypeNpde(node.AsQuantifiedTypeNode()) case ast.KindExpressionWithTypeArguments: // !!! Should this actually be considered a type? diff --git a/testdata/baselines/reference/compiler/allowQuantifiedTypes.js b/testdata/baselines/reference/compiler/allowQuantifiedTypes.js new file mode 100644 index 0000000000..94e01d9ba6 --- /dev/null +++ b/testdata/baselines/reference/compiler/allowQuantifiedTypes.js @@ -0,0 +1,8 @@ +//// [tests/cases/compiler/allowQuantifiedTypes.ts] //// + +//// [allowQuantifiedTypes.ts] +type T0 = { values: T[], identifier: (value: T) => string } +type T1 = (t: T) => T +type T2 = (u: U) => U + +//// [allowQuantifiedTypes.js] diff --git a/testdata/baselines/reference/compiler/allowQuantifiedTypes.symbols b/testdata/baselines/reference/compiler/allowQuantifiedTypes.symbols new file mode 100644 index 0000000000..e8ead920d7 --- /dev/null +++ b/testdata/baselines/reference/compiler/allowQuantifiedTypes.symbols @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/allowQuantifiedTypes.ts] //// + +=== allowQuantifiedTypes.ts === +type T0 = { values: T[], identifier: (value: T) => string } +>T0 : Symbol(T0, Decl(allowQuantifiedTypes.ts, 0, 0)) +>T : Symbol(T, Decl(allowQuantifiedTypes.ts, 0, 11)) +>values : Symbol(values, Decl(allowQuantifiedTypes.ts, 0, 30)) +>T : Symbol(T, Decl(allowQuantifiedTypes.ts, 0, 11)) +>identifier : Symbol(identifier, Decl(allowQuantifiedTypes.ts, 0, 43)) +>value : Symbol(value, Decl(allowQuantifiedTypes.ts, 0, 57)) +>T : Symbol(T, Decl(allowQuantifiedTypes.ts, 0, 11)) + +type T1 = (t: T) => T +>T1 : Symbol(T1, Decl(allowQuantifiedTypes.ts, 0, 78)) +>T : Symbol(T, Decl(allowQuantifiedTypes.ts, 1, 11)) +>t : Symbol(t, Decl(allowQuantifiedTypes.ts, 1, 29)) +>T : Symbol(T, Decl(allowQuantifiedTypes.ts, 1, 11)) +>T : Symbol(T, Decl(allowQuantifiedTypes.ts, 1, 11)) + +type T2 = (u: U) => U +>T2 : Symbol(T2, Decl(allowQuantifiedTypes.ts, 1, 39)) +>T : Symbol(T, Decl(allowQuantifiedTypes.ts, 2, 11)) +>U : Symbol(U, Decl(allowQuantifiedTypes.ts, 2, 30)) +>T : Symbol(T, Decl(allowQuantifiedTypes.ts, 2, 11)) +>u : Symbol(u, Decl(allowQuantifiedTypes.ts, 2, 43)) +>U : Symbol(U, Decl(allowQuantifiedTypes.ts, 2, 30)) +>U : Symbol(U, Decl(allowQuantifiedTypes.ts, 2, 30)) + diff --git a/testdata/baselines/reference/compiler/allowQuantifiedTypes.types b/testdata/baselines/reference/compiler/allowQuantifiedTypes.types new file mode 100644 index 0000000000..600f750c1d --- /dev/null +++ b/testdata/baselines/reference/compiler/allowQuantifiedTypes.types @@ -0,0 +1,17 @@ +//// [tests/cases/compiler/allowQuantifiedTypes.ts] //// + +=== allowQuantifiedTypes.ts === +type T0 = { values: T[], identifier: (value: T) => string } +>T0 : { values: T[]; identifier: (value: T) => string; } +>values : T[] +>identifier : (value: T) => string +>value : T + +type T1 = (t: T) => T +>T1 : T1 +>t : T + +type T2 = (u: U) => U +>T2 : (u: U) => U +>u : U + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesAdvanced.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesAdvanced.errors.txt new file mode 100644 index 0000000000..adeb814c1c --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesAdvanced.errors.txt @@ -0,0 +1,48 @@ +quantifiedTypesAdvanced.ts(28,5): error TS2322: Type 'boolean' is not assignable to type 'string | number'. +quantifiedTypesAdvanced.ts(36,5): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ a: "hello"; ab: (a: "hello") => string; bc?: (b: string) => number; }'. + + +==== quantifiedTypesAdvanced.ts (2 errors) ==== + declare const f: + { a: A, ab: (a: A) => B, bc?: (b: B) => C })[]>(a: [...T]) => + { [K in keyof T]: T[K] extends { bc: (...a: never) => infer C } ? C : "lol" } + + let t0 = f([ + { + a: "0", + ab: a => +a, + bc: b => typeof b === "number" + }, + { + a: "hello", + ab: a => a + " world", + bc: b => { + b satisfies string + return +b + } + }, + { + a: 42, + ab: a => a.toString() + } + ]) + + + let t1 = f([ + { + a: true, + ~ +!!! error TS2322: Type 'boolean' is not assignable to type 'string | number'. +!!! related TS6500 quantifiedTypesAdvanced.ts:2:51: The expected type comes from property 'a' which is declared here on type '{ a: string | number; ab: (a: string | number) => number; bc?: (b: number) => boolean; }' + ab: a => +a, + bc: b => typeof b === "number" + }, + { + a: "hello", + ab: a => a + " world", + bc: b => +b, + extra: "foo" // TODO: an extra property should be allowed + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ a: "hello"; ab: (a: "hello") => string; bc?: (b: string) => number; }'. + } + ]) \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesAdvanced.js b/testdata/baselines/reference/compiler/quantifiedTypesAdvanced.js new file mode 100644 index 0000000000..0124660873 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesAdvanced.js @@ -0,0 +1,75 @@ +//// [tests/cases/compiler/quantifiedTypesAdvanced.ts] //// + +//// [quantifiedTypesAdvanced.ts] +declare const f: + { a: A, ab: (a: A) => B, bc?: (b: B) => C })[]>(a: [...T]) => + { [K in keyof T]: T[K] extends { bc: (...a: never) => infer C } ? C : "lol" } + +let t0 = f([ + { + a: "0", + ab: a => +a, + bc: b => typeof b === "number" + }, + { + a: "hello", + ab: a => a + " world", + bc: b => { + b satisfies string + return +b + } + }, + { + a: 42, + ab: a => a.toString() + } +]) + + +let t1 = f([ + { + a: true, + ab: a => +a, + bc: b => typeof b === "number" + }, + { + a: "hello", + ab: a => a + " world", + bc: b => +b, + extra: "foo" // TODO: an extra property should be allowed + } +]) + +//// [quantifiedTypesAdvanced.js] +let t0 = f([ + { + a: "0", + ab: a => +a, + bc: b => typeof b === "number" + }, + { + a: "hello", + ab: a => a + " world", + bc: b => { + b; + return +b; + } + }, + { + a: 42, + ab: a => a.toString() + } +]); +let t1 = f([ + { + a: true, + ab: a => +a, + bc: b => typeof b === "number" + }, + { + a: "hello", + ab: a => a + " world", + bc: b => +b, + extra: "foo" // TODO: an extra property should be allowed + } +]); diff --git a/testdata/baselines/reference/compiler/quantifiedTypesAdvanced.symbols b/testdata/baselines/reference/compiler/quantifiedTypesAdvanced.symbols new file mode 100644 index 0000000000..1fd1571ee0 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesAdvanced.symbols @@ -0,0 +1,122 @@ +//// [tests/cases/compiler/quantifiedTypesAdvanced.ts] //// + +=== quantifiedTypesAdvanced.ts === +declare const f: +>f : Symbol(f, Decl(quantifiedTypesAdvanced.ts, 0, 13)) + + { a: A, ab: (a: A) => B, bc?: (b: B) => C })[]>(a: [...T]) => +>T : Symbol(T, Decl(quantifiedTypesAdvanced.ts, 1, 3)) +>A : Symbol(A, Decl(quantifiedTypesAdvanced.ts, 1, 15)) +>B : Symbol(B, Decl(quantifiedTypesAdvanced.ts, 1, 41)) +>C : Symbol(C, Decl(quantifiedTypesAdvanced.ts, 1, 44)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 1, 49)) +>A : Symbol(A, Decl(quantifiedTypesAdvanced.ts, 1, 15)) +>ab : Symbol(ab, Decl(quantifiedTypesAdvanced.ts, 1, 55)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 1, 61)) +>A : Symbol(A, Decl(quantifiedTypesAdvanced.ts, 1, 15)) +>B : Symbol(B, Decl(quantifiedTypesAdvanced.ts, 1, 41)) +>bc : Symbol(bc, Decl(quantifiedTypesAdvanced.ts, 1, 72)) +>b : Symbol(b, Decl(quantifiedTypesAdvanced.ts, 1, 79)) +>B : Symbol(B, Decl(quantifiedTypesAdvanced.ts, 1, 41)) +>C : Symbol(C, Decl(quantifiedTypesAdvanced.ts, 1, 44)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 1, 96)) +>T : Symbol(T, Decl(quantifiedTypesAdvanced.ts, 1, 3)) + + { [K in keyof T]: T[K] extends { bc: (...a: never) => infer C } ? C : "lol" } +>K : Symbol(K, Decl(quantifiedTypesAdvanced.ts, 2, 9)) +>T : Symbol(T, Decl(quantifiedTypesAdvanced.ts, 1, 3)) +>T : Symbol(T, Decl(quantifiedTypesAdvanced.ts, 1, 3)) +>K : Symbol(K, Decl(quantifiedTypesAdvanced.ts, 2, 9)) +>bc : Symbol(bc, Decl(quantifiedTypesAdvanced.ts, 2, 38)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 2, 44)) +>C : Symbol(C, Decl(quantifiedTypesAdvanced.ts, 2, 65)) +>C : Symbol(C, Decl(quantifiedTypesAdvanced.ts, 2, 65)) + +let t0 = f([ +>t0 : Symbol(t0, Decl(quantifiedTypesAdvanced.ts, 4, 3)) +>f : Symbol(f, Decl(quantifiedTypesAdvanced.ts, 0, 13)) + { + a: "0", +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 5, 3)) + + ab: a => +a, +>ab : Symbol(ab, Decl(quantifiedTypesAdvanced.ts, 6, 11)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 7, 7)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 7, 7)) + + bc: b => typeof b === "number" +>bc : Symbol(bc, Decl(quantifiedTypesAdvanced.ts, 7, 16)) +>b : Symbol(b, Decl(quantifiedTypesAdvanced.ts, 8, 7)) +>b : Symbol(b, Decl(quantifiedTypesAdvanced.ts, 8, 7)) + + }, + { + a: "hello", +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 10, 3)) + + ab: a => a + " world", +>ab : Symbol(ab, Decl(quantifiedTypesAdvanced.ts, 11, 15)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 12, 7)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 12, 7)) + + bc: b => { +>bc : Symbol(bc, Decl(quantifiedTypesAdvanced.ts, 12, 26)) +>b : Symbol(b, Decl(quantifiedTypesAdvanced.ts, 13, 7)) + + b satisfies string +>b : Symbol(b, Decl(quantifiedTypesAdvanced.ts, 13, 7)) + + return +b +>b : Symbol(b, Decl(quantifiedTypesAdvanced.ts, 13, 7)) + } + }, + { + a: 42, +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 18, 3)) + + ab: a => a.toString() +>ab : Symbol(ab, Decl(quantifiedTypesAdvanced.ts, 19, 10)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 20, 7)) +>a.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 20, 7)) +>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) + } +]) + + +let t1 = f([ +>t1 : Symbol(t1, Decl(quantifiedTypesAdvanced.ts, 25, 3)) +>f : Symbol(f, Decl(quantifiedTypesAdvanced.ts, 0, 13)) + { + a: true, +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 26, 3)) + + ab: a => +a, +>ab : Symbol(ab, Decl(quantifiedTypesAdvanced.ts, 27, 12)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 28, 7)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 28, 7)) + + bc: b => typeof b === "number" +>bc : Symbol(bc, Decl(quantifiedTypesAdvanced.ts, 28, 16)) +>b : Symbol(b, Decl(quantifiedTypesAdvanced.ts, 29, 7)) +>b : Symbol(b, Decl(quantifiedTypesAdvanced.ts, 29, 7)) + + }, + { + a: "hello", +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 31, 3)) + + ab: a => a + " world", +>ab : Symbol(ab, Decl(quantifiedTypesAdvanced.ts, 32, 15)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 33, 7)) +>a : Symbol(a, Decl(quantifiedTypesAdvanced.ts, 33, 7)) + + bc: b => +b, +>bc : Symbol(bc, Decl(quantifiedTypesAdvanced.ts, 33, 26)) +>b : Symbol(b, Decl(quantifiedTypesAdvanced.ts, 34, 7)) +>b : Symbol(b, Decl(quantifiedTypesAdvanced.ts, 34, 7)) + + extra: "foo" // TODO: an extra property should be allowed +>extra : Symbol(extra, Decl(quantifiedTypesAdvanced.ts, 34, 16)) + } +]) diff --git a/testdata/baselines/reference/compiler/quantifiedTypesAdvanced.types b/testdata/baselines/reference/compiler/quantifiedTypesAdvanced.types new file mode 100644 index 0000000000..b7d1ffad49 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesAdvanced.types @@ -0,0 +1,151 @@ +//// [tests/cases/compiler/quantifiedTypesAdvanced.ts] //// + +=== quantifiedTypesAdvanced.ts === +declare const f: +>f : { a: A; ab: (a: A) => B; bc?: (b: B) => C; })[]>(a: [...T]) => { [K in keyof T]: T[K] extends { bc: (...a: never) => infer C_1; } ? C_1 : "lol"; } + + { a: A, ab: (a: A) => B, bc?: (b: B) => C })[]>(a: [...T]) => +>a : A +>ab : (a: A) => B +>a : A +>bc : (b: B) => C +>b : B +>a : [...T] + + { [K in keyof T]: T[K] extends { bc: (...a: never) => infer C } ? C : "lol" } +>bc : (...a: never) => C +>a : never + +let t0 = f([ +>t0 : [boolean, number, "lol"] +>f([ { a: "0", ab: a => +a, bc: b => typeof b === "number" }, { a: "hello", ab: a => a + " world", bc: b => { b satisfies string return +b } }, { a: 42, ab: a => a.toString() }]) : [boolean, number, "lol"] +>f : { a: A; ab: (a: A) => B; bc?: (b: B) => C; })[]>(a: [...T]) => { [K in keyof T]: T[K] extends { bc: (...a: never) => infer C_1; } ? C_1 : "lol"; } +>[ { a: "0", ab: a => +a, bc: b => typeof b === "number" }, { a: "hello", ab: a => a + " world", bc: b => { b satisfies string return +b } }, { a: 42, ab: a => a.toString() }] : [{ a: "0"; ab: (a: "0") => number; bc: (b: number) => boolean; }, { a: "hello"; ab: (a: "hello") => string; bc: (b: string) => number; }, { a: 42; ab: (a: 42) => string; }] + { +>{ a: "0", ab: a => +a, bc: b => typeof b === "number" } : { a: "0"; ab: (a: "0") => number; bc: (b: number) => boolean; } + + a: "0", +>a : "0" +>"0" : "0" + + ab: a => +a, +>ab : (a: "0") => number +>a => +a : (a: "0") => number +>a : "0" +>+a : number +>a : "0" + + bc: b => typeof b === "number" +>bc : (b: number) => boolean +>b => typeof b === "number" : (b: number) => boolean +>b : number +>typeof b === "number" : boolean +>typeof b : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>b : number +>"number" : "number" + + }, + { +>{ a: "hello", ab: a => a + " world", bc: b => { b satisfies string return +b } } : { a: "hello"; ab: (a: "hello") => string; bc: (b: string) => number; } + + a: "hello", +>a : "hello" +>"hello" : "hello" + + ab: a => a + " world", +>ab : (a: "hello") => string +>a => a + " world" : (a: "hello") => string +>a : "hello" +>a + " world" : string +>a : "hello" +>" world" : " world" + + bc: b => { +>bc : (b: string) => number +>b => { b satisfies string return +b } : (b: string) => number +>b : string + + b satisfies string +>b satisfies string : string +>b : string + + return +b +>+b : number +>b : string + } + }, + { +>{ a: 42, ab: a => a.toString() } : { a: 42; ab: (a: 42) => string; } + + a: 42, +>a : 42 +>42 : 42 + + ab: a => a.toString() +>ab : (a: 42) => string +>a => a.toString() : (a: 42) => string +>a : 42 +>a.toString() : string +>a.toString : (radix?: number) => string +>a : 42 +>toString : (radix?: number) => string + } +]) + + +let t1 = f([ +>t1 : (( { a: A; ab: (a: A) => B; bc?: (b: B) => C; }) extends { bc: (...a: never) => infer C_1; } ? C_1 : "lol")[] +>f([ { a: true, ab: a => +a, bc: b => typeof b === "number" }, { a: "hello", ab: a => a + " world", bc: b => +b, extra: "foo" // TODO: an extra property should be allowed }]) : (( { a: A; ab: (a: A) => B; bc?: (b: B) => C; }) extends { bc: (...a: never) => infer C_1; } ? C_1 : "lol")[] +>f : { a: A; ab: (a: A) => B; bc?: (b: B) => C; })[]>(a: [...T]) => { [K in keyof T]: T[K] extends { bc: (...a: never) => infer C_1; } ? C_1 : "lol"; } +>[ { a: true, ab: a => +a, bc: b => typeof b === "number" }, { a: "hello", ab: a => a + " world", bc: b => +b, extra: "foo" // TODO: an extra property should be allowed }] : any[] + { +>{ a: true, ab: a => +a, bc: b => typeof b === "number" } : any + + a: true, +>a : boolean +>true : true + + ab: a => +a, +>ab : (a: string | number) => number +>a => +a : (a: string | number) => number +>a : string | number +>+a : number +>a : string | number + + bc: b => typeof b === "number" +>bc : (b: number) => boolean +>b => typeof b === "number" : (b: number) => boolean +>b : number +>typeof b === "number" : boolean +>typeof b : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>b : number +>"number" : "number" + + }, + { +>{ a: "hello", ab: a => a + " world", bc: b => +b, extra: "foo" // TODO: an extra property should be allowed } : any + + a: "hello", +>a : string +>"hello" : "hello" + + ab: a => a + " world", +>ab : (a: "hello") => string +>a => a + " world" : (a: "hello") => string +>a : "hello" +>a + " world" : string +>a : "hello" +>" world" : " world" + + bc: b => +b, +>bc : (b: string) => number +>b => +b : (b: string) => number +>b : string +>+b : number +>b : string + + extra: "foo" // TODO: an extra property should be allowed +>extra : string +>"foo" : "foo" + } +]) diff --git a/testdata/baselines/reference/compiler/quantifiedTypesBasic.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesBasic.errors.txt new file mode 100644 index 0000000000..38148ca7e8 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesBasic.errors.txt @@ -0,0 +1,21 @@ +quantifiedTypesBasic.ts(10,20): error TS2322: Type 'string | number' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. + + +==== quantifiedTypesBasic.ts (1 errors) ==== + let t0: T = "hello" + + let t1: { values: T[], identifier: (value: T) => string } = { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + } + + let t2: { values: T[], identifier: (value: T) => string } = { + values: [{ key: "a" }, { key: "b" }, { key: 0 }], + identifier: v => v.key + ~~~~~ +!!! error TS2322: Type 'string | number' is not assignable to type 'string'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! related TS6502 quantifiedTypesBasic.ts:8:40: The expected type comes from the return type of this signature. + } + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesBasic.js b/testdata/baselines/reference/compiler/quantifiedTypesBasic.js new file mode 100644 index 0000000000..d4bdf87766 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesBasic.js @@ -0,0 +1,26 @@ +//// [tests/cases/compiler/quantifiedTypesBasic.ts] //// + +//// [quantifiedTypesBasic.ts] +let t0: T = "hello" + +let t1: { values: T[], identifier: (value: T) => string } = { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key +} + +let t2: { values: T[], identifier: (value: T) => string } = { + values: [{ key: "a" }, { key: "b" }, { key: 0 }], + identifier: v => v.key +} + + +//// [quantifiedTypesBasic.js] +let t0 = "hello"; +let t1 = { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key +}; +let t2 = { + values: [{ key: "a" }, { key: "b" }, { key: 0 }], + identifier: v => v.key +}; diff --git a/testdata/baselines/reference/compiler/quantifiedTypesBasic.symbols b/testdata/baselines/reference/compiler/quantifiedTypesBasic.symbols new file mode 100644 index 0000000000..cf4677eeb3 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesBasic.symbols @@ -0,0 +1,54 @@ +//// [tests/cases/compiler/quantifiedTypesBasic.ts] //// + +=== quantifiedTypesBasic.ts === +let t0: T = "hello" +>t0 : Symbol(t0, Decl(quantifiedTypesBasic.ts, 0, 3)) +>T : Symbol(T, Decl(quantifiedTypesBasic.ts, 0, 9)) +>T : Symbol(T, Decl(quantifiedTypesBasic.ts, 0, 9)) + +let t1: { values: T[], identifier: (value: T) => string } = { +>t1 : Symbol(t1, Decl(quantifiedTypesBasic.ts, 2, 3)) +>T : Symbol(T, Decl(quantifiedTypesBasic.ts, 2, 9)) +>values : Symbol(values, Decl(quantifiedTypesBasic.ts, 2, 13)) +>T : Symbol(T, Decl(quantifiedTypesBasic.ts, 2, 9)) +>identifier : Symbol(identifier, Decl(quantifiedTypesBasic.ts, 2, 26)) +>value : Symbol(value, Decl(quantifiedTypesBasic.ts, 2, 40)) +>T : Symbol(T, Decl(quantifiedTypesBasic.ts, 2, 9)) + + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : Symbol(values, Decl(quantifiedTypesBasic.ts, 2, 65)) +>key : Symbol(key, Decl(quantifiedTypesBasic.ts, 3, 12)) +>key : Symbol(key, Decl(quantifiedTypesBasic.ts, 3, 26)) +>key : Symbol(key, Decl(quantifiedTypesBasic.ts, 3, 40)) + + identifier: v => v.key +>identifier : Symbol(identifier, Decl(quantifiedTypesBasic.ts, 3, 53)) +>v : Symbol(v, Decl(quantifiedTypesBasic.ts, 4, 13)) +>v.key : Symbol(key, Decl(quantifiedTypesBasic.ts, 3, 12)) +>v : Symbol(v, Decl(quantifiedTypesBasic.ts, 4, 13)) +>key : Symbol(key, Decl(quantifiedTypesBasic.ts, 3, 12)) +} + +let t2: { values: T[], identifier: (value: T) => string } = { +>t2 : Symbol(t2, Decl(quantifiedTypesBasic.ts, 7, 3)) +>T : Symbol(T, Decl(quantifiedTypesBasic.ts, 7, 9)) +>values : Symbol(values, Decl(quantifiedTypesBasic.ts, 7, 13)) +>T : Symbol(T, Decl(quantifiedTypesBasic.ts, 7, 9)) +>identifier : Symbol(identifier, Decl(quantifiedTypesBasic.ts, 7, 26)) +>value : Symbol(value, Decl(quantifiedTypesBasic.ts, 7, 40)) +>T : Symbol(T, Decl(quantifiedTypesBasic.ts, 7, 9)) + + values: [{ key: "a" }, { key: "b" }, { key: 0 }], +>values : Symbol(values, Decl(quantifiedTypesBasic.ts, 7, 65)) +>key : Symbol(key, Decl(quantifiedTypesBasic.ts, 8, 12)) +>key : Symbol(key, Decl(quantifiedTypesBasic.ts, 8, 26)) +>key : Symbol(key, Decl(quantifiedTypesBasic.ts, 8, 40)) + + identifier: v => v.key +>identifier : Symbol(identifier, Decl(quantifiedTypesBasic.ts, 8, 51)) +>v : Symbol(v, Decl(quantifiedTypesBasic.ts, 9, 13)) +>v.key : Symbol(key, Decl(quantifiedTypesBasic.ts, 8, 12), Decl(quantifiedTypesBasic.ts, 8, 40)) +>v : Symbol(v, Decl(quantifiedTypesBasic.ts, 9, 13)) +>key : Symbol(key, Decl(quantifiedTypesBasic.ts, 8, 12), Decl(quantifiedTypesBasic.ts, 8, 40)) +} + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesBasic.types b/testdata/baselines/reference/compiler/quantifiedTypesBasic.types new file mode 100644 index 0000000000..1908d24f2a --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesBasic.types @@ -0,0 +1,65 @@ +//// [tests/cases/compiler/quantifiedTypesBasic.ts] //// + +=== quantifiedTypesBasic.ts === +let t0: T = "hello" +>t0 : T +>"hello" : "hello" + +let t1: { values: T[], identifier: (value: T) => string } = { +>t1 : { values: T[]; identifier: (value: T) => string; } +>values : T[] +>identifier : (value: T) => string +>value : T +>{ values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => v.key} : { values: { key: string; }[]; identifier: (v: { key: string; }) => string; } + + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : { key: string; }[] +>[{ key: "a" }, { key: "b" }, { key: "c" }] : { key: string; }[] +>{ key: "a" } : { key: string; } +>key : string +>"a" : "a" +>{ key: "b" } : { key: string; } +>key : string +>"b" : "b" +>{ key: "c" } : { key: string; } +>key : string +>"c" : "c" + + identifier: v => v.key +>identifier : (v: { key: string; }) => string +>v => v.key : (v: { key: string; }) => string +>v : { key: string; } +>v.key : string +>v : { key: string; } +>key : string +} + +let t2: { values: T[], identifier: (value: T) => string } = { +>t2 : { values: T[]; identifier: (value: T) => string; } +>values : T[] +>identifier : (value: T) => string +>value : T +>{ values: [{ key: "a" }, { key: "b" }, { key: 0 }], identifier: v => v.key} : any + + values: [{ key: "a" }, { key: "b" }, { key: 0 }], +>values : ({ key: string; } | { key: number; })[] +>[{ key: "a" }, { key: "b" }, { key: 0 }] : ({ key: string; } | { key: number; })[] +>{ key: "a" } : { key: string; } +>key : string +>"a" : "a" +>{ key: "b" } : { key: string; } +>key : string +>"b" : "b" +>{ key: 0 } : { key: number; } +>key : number +>0 : 0 + + identifier: v => v.key +>identifier : (v: { key: string; } | { key: number; }) => string | number +>v => v.key : (v: { key: string; } | { key: number; }) => string | number +>v : { key: string; } | { key: number; } +>v.key : string | number +>v : { key: string; } | { key: number; } +>key : string | number +} + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesBasic2.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesBasic2.errors.txt new file mode 100644 index 0000000000..3e04efef51 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesBasic2.errors.txt @@ -0,0 +1,22 @@ +quantifiedTypesBasic2.ts(11,20): error TS2322: Type 'string | number' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. + + +==== quantifiedTypesBasic2.ts (1 errors) ==== + declare const f1: (t: T) => void + f1("hello") + + declare const f2: (t: { values: T[], identifier: (value: T) => string }) => void + f2({ + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + }) + f2({ + values: [{ key: "a" }, { key: "b" }, { key: 0 }], + identifier: v => v.key + ~~~~~ +!!! error TS2322: Type 'string | number' is not assignable to type 'string'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! related TS6502 quantifiedTypesBasic2.ts:4:54: The expected type comes from the return type of this signature. + }) + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesBasic2.js b/testdata/baselines/reference/compiler/quantifiedTypesBasic2.js new file mode 100644 index 0000000000..014c66f234 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesBasic2.js @@ -0,0 +1,27 @@ +//// [tests/cases/compiler/quantifiedTypesBasic2.ts] //// + +//// [quantifiedTypesBasic2.ts] +declare const f1: (t: T) => void +f1("hello") + +declare const f2: (t: { values: T[], identifier: (value: T) => string }) => void +f2({ + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key +}) +f2({ + values: [{ key: "a" }, { key: "b" }, { key: 0 }], + identifier: v => v.key +}) + + +//// [quantifiedTypesBasic2.js] +f1("hello"); +f2({ + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key +}); +f2({ + values: [{ key: "a" }, { key: "b" }, { key: 0 }], + identifier: v => v.key +}); diff --git a/testdata/baselines/reference/compiler/quantifiedTypesBasic2.symbols b/testdata/baselines/reference/compiler/quantifiedTypesBasic2.symbols new file mode 100644 index 0000000000..a5cca619d1 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesBasic2.symbols @@ -0,0 +1,57 @@ +//// [tests/cases/compiler/quantifiedTypesBasic2.ts] //// + +=== quantifiedTypesBasic2.ts === +declare const f1: (t: T) => void +>f1 : Symbol(f1, Decl(quantifiedTypesBasic2.ts, 0, 13)) +>t : Symbol(t, Decl(quantifiedTypesBasic2.ts, 0, 19)) +>T : Symbol(T, Decl(quantifiedTypesBasic2.ts, 0, 23)) +>T : Symbol(T, Decl(quantifiedTypesBasic2.ts, 0, 23)) + +f1("hello") +>f1 : Symbol(f1, Decl(quantifiedTypesBasic2.ts, 0, 13)) + +declare const f2: (t: { values: T[], identifier: (value: T) => string }) => void +>f2 : Symbol(f2, Decl(quantifiedTypesBasic2.ts, 3, 13)) +>t : Symbol(t, Decl(quantifiedTypesBasic2.ts, 3, 19)) +>T : Symbol(T, Decl(quantifiedTypesBasic2.ts, 3, 23)) +>values : Symbol(values, Decl(quantifiedTypesBasic2.ts, 3, 27)) +>T : Symbol(T, Decl(quantifiedTypesBasic2.ts, 3, 23)) +>identifier : Symbol(identifier, Decl(quantifiedTypesBasic2.ts, 3, 40)) +>value : Symbol(value, Decl(quantifiedTypesBasic2.ts, 3, 54)) +>T : Symbol(T, Decl(quantifiedTypesBasic2.ts, 3, 23)) + +f2({ +>f2 : Symbol(f2, Decl(quantifiedTypesBasic2.ts, 3, 13)) + + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : Symbol(values, Decl(quantifiedTypesBasic2.ts, 4, 4)) +>key : Symbol(key, Decl(quantifiedTypesBasic2.ts, 5, 12)) +>key : Symbol(key, Decl(quantifiedTypesBasic2.ts, 5, 26)) +>key : Symbol(key, Decl(quantifiedTypesBasic2.ts, 5, 40)) + + identifier: v => v.key +>identifier : Symbol(identifier, Decl(quantifiedTypesBasic2.ts, 5, 53)) +>v : Symbol(v, Decl(quantifiedTypesBasic2.ts, 6, 13)) +>v.key : Symbol(key, Decl(quantifiedTypesBasic2.ts, 5, 12)) +>v : Symbol(v, Decl(quantifiedTypesBasic2.ts, 6, 13)) +>key : Symbol(key, Decl(quantifiedTypesBasic2.ts, 5, 12)) + +}) +f2({ +>f2 : Symbol(f2, Decl(quantifiedTypesBasic2.ts, 3, 13)) + + values: [{ key: "a" }, { key: "b" }, { key: 0 }], +>values : Symbol(values, Decl(quantifiedTypesBasic2.ts, 8, 4)) +>key : Symbol(key, Decl(quantifiedTypesBasic2.ts, 9, 12)) +>key : Symbol(key, Decl(quantifiedTypesBasic2.ts, 9, 26)) +>key : Symbol(key, Decl(quantifiedTypesBasic2.ts, 9, 40)) + + identifier: v => v.key +>identifier : Symbol(identifier, Decl(quantifiedTypesBasic2.ts, 9, 51)) +>v : Symbol(v, Decl(quantifiedTypesBasic2.ts, 10, 13)) +>v.key : Symbol(key, Decl(quantifiedTypesBasic2.ts, 9, 12), Decl(quantifiedTypesBasic2.ts, 9, 40)) +>v : Symbol(v, Decl(quantifiedTypesBasic2.ts, 10, 13)) +>key : Symbol(key, Decl(quantifiedTypesBasic2.ts, 9, 12), Decl(quantifiedTypesBasic2.ts, 9, 40)) + +}) + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesBasic2.types b/testdata/baselines/reference/compiler/quantifiedTypesBasic2.types new file mode 100644 index 0000000000..a5f6f0f448 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesBasic2.types @@ -0,0 +1,74 @@ +//// [tests/cases/compiler/quantifiedTypesBasic2.ts] //// + +=== quantifiedTypesBasic2.ts === +declare const f1: (t: T) => void +>f1 : (t: T) => void +>t : T + +f1("hello") +>f1("hello") : void +>f1 : (t: T) => void +>"hello" : "hello" + +declare const f2: (t: { values: T[], identifier: (value: T) => string }) => void +>f2 : (t: { values: T[]; identifier: (value: T) => string; }) => void +>t : { values: T[]; identifier: (value: T) => string; } +>values : T[] +>identifier : (value: T) => string +>value : T + +f2({ +>f2({ values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => v.key}) : void +>f2 : (t: { values: T[]; identifier: (value: T) => string; }) => void +>{ values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => v.key} : { values: { key: string; }[]; identifier: (v: { key: string; }) => string; } + + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : { key: string; }[] +>[{ key: "a" }, { key: "b" }, { key: "c" }] : { key: string; }[] +>{ key: "a" } : { key: string; } +>key : string +>"a" : "a" +>{ key: "b" } : { key: string; } +>key : string +>"b" : "b" +>{ key: "c" } : { key: string; } +>key : string +>"c" : "c" + + identifier: v => v.key +>identifier : (v: { key: string; }) => string +>v => v.key : (v: { key: string; }) => string +>v : { key: string; } +>v.key : string +>v : { key: string; } +>key : string + +}) +f2({ +>f2({ values: [{ key: "a" }, { key: "b" }, { key: 0 }], identifier: v => v.key}) : void +>f2 : (t: { values: T[]; identifier: (value: T) => string; }) => void +>{ values: [{ key: "a" }, { key: "b" }, { key: 0 }], identifier: v => v.key} : any + + values: [{ key: "a" }, { key: "b" }, { key: 0 }], +>values : ({ key: string; } | { key: number; })[] +>[{ key: "a" }, { key: "b" }, { key: 0 }] : ({ key: string; } | { key: number; })[] +>{ key: "a" } : { key: string; } +>key : string +>"a" : "a" +>{ key: "b" } : { key: string; } +>key : string +>"b" : "b" +>{ key: 0 } : { key: number; } +>key : number +>0 : 0 + + identifier: v => v.key +>identifier : (v: { key: string; } | { key: number; }) => string | number +>v => v.key : (v: { key: string; } | { key: number; }) => string | number +>v : { key: string; } | { key: number; } +>v.key : string | number +>v : { key: string; } | { key: number; } +>key : string | number + +}) + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesConstraints.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesConstraints.errors.txt new file mode 100644 index 0000000000..709c2fa0a5 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesConstraints.errors.txt @@ -0,0 +1,23 @@ +quantifiedTypesConstraints.ts(5,12): error TS2322: Type 'string' is not assignable to type 'object'. +quantifiedTypesConstraints.ts(5,17): error TS2322: Type 'string' is not assignable to type 'object'. +quantifiedTypesConstraints.ts(5,22): error TS2322: Type 'string' is not assignable to type 'object'. +quantifiedTypesConstraints.ts(6,20): error TS2322: Type 'object' is not assignable to type 'string'. + + +==== quantifiedTypesConstraints.ts (4 errors) ==== + type Input = { values: T[], identifier: (value: T) => string } + declare const f: (t: Input) => void + + f({ + values: ["a", "b", "c"], + ~~~ +!!! error TS2322: Type 'string' is not assignable to type 'object'. + ~~~ +!!! error TS2322: Type 'string' is not assignable to type 'object'. + ~~~ +!!! error TS2322: Type 'string' is not assignable to type 'object'. + identifier: v => v + ~ +!!! error TS2322: Type 'object' is not assignable to type 'string'. +!!! related TS6502 quantifiedTypesConstraints.ts:1:44: The expected type comes from the return type of this signature. + }) \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesConstraints.js b/testdata/baselines/reference/compiler/quantifiedTypesConstraints.js new file mode 100644 index 0000000000..957017a7b0 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesConstraints.js @@ -0,0 +1,16 @@ +//// [tests/cases/compiler/quantifiedTypesConstraints.ts] //// + +//// [quantifiedTypesConstraints.ts] +type Input = { values: T[], identifier: (value: T) => string } +declare const f: (t: Input) => void + +f({ + values: ["a", "b", "c"], + identifier: v => v +}) + +//// [quantifiedTypesConstraints.js] +f({ + values: ["a", "b", "c"], + identifier: v => v +}); diff --git a/testdata/baselines/reference/compiler/quantifiedTypesConstraints.symbols b/testdata/baselines/reference/compiler/quantifiedTypesConstraints.symbols new file mode 100644 index 0000000000..3099c513f4 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesConstraints.symbols @@ -0,0 +1,31 @@ +//// [tests/cases/compiler/quantifiedTypesConstraints.ts] //// + +=== quantifiedTypesConstraints.ts === +type Input = { values: T[], identifier: (value: T) => string } +>Input : Symbol(Input, Decl(quantifiedTypesConstraints.ts, 0, 0)) +>T : Symbol(T, Decl(quantifiedTypesConstraints.ts, 0, 11)) +>values : Symbol(values, Decl(quantifiedTypesConstraints.ts, 0, 17)) +>T : Symbol(T, Decl(quantifiedTypesConstraints.ts, 0, 11)) +>identifier : Symbol(identifier, Decl(quantifiedTypesConstraints.ts, 0, 30)) +>value : Symbol(value, Decl(quantifiedTypesConstraints.ts, 0, 44)) +>T : Symbol(T, Decl(quantifiedTypesConstraints.ts, 0, 11)) + +declare const f: (t: Input) => void +>f : Symbol(f, Decl(quantifiedTypesConstraints.ts, 1, 13)) +>t : Symbol(t, Decl(quantifiedTypesConstraints.ts, 1, 18)) +>T : Symbol(T, Decl(quantifiedTypesConstraints.ts, 1, 22)) +>Input : Symbol(Input, Decl(quantifiedTypesConstraints.ts, 0, 0)) +>T : Symbol(T, Decl(quantifiedTypesConstraints.ts, 1, 22)) + +f({ +>f : Symbol(f, Decl(quantifiedTypesConstraints.ts, 1, 13)) + + values: ["a", "b", "c"], +>values : Symbol(values, Decl(quantifiedTypesConstraints.ts, 3, 3)) + + identifier: v => v +>identifier : Symbol(identifier, Decl(quantifiedTypesConstraints.ts, 4, 26)) +>v : Symbol(v, Decl(quantifiedTypesConstraints.ts, 5, 13)) +>v : Symbol(v, Decl(quantifiedTypesConstraints.ts, 5, 13)) + +}) diff --git a/testdata/baselines/reference/compiler/quantifiedTypesConstraints.types b/testdata/baselines/reference/compiler/quantifiedTypesConstraints.types new file mode 100644 index 0000000000..82d96e3f35 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesConstraints.types @@ -0,0 +1,32 @@ +//// [tests/cases/compiler/quantifiedTypesConstraints.ts] //// + +=== quantifiedTypesConstraints.ts === +type Input = { values: T[], identifier: (value: T) => string } +>Input : Input +>values : T[] +>identifier : (value: T) => string +>value : T + +declare const f: (t: Input) => void +>f : (t: Input) => void +>t : Input + +f({ +>f({ values: ["a", "b", "c"], identifier: v => v}) : void +>f : (t: Input) => void +>{ values: ["a", "b", "c"], identifier: v => v} : any + + values: ["a", "b", "c"], +>values : string[] +>["a", "b", "c"] : string[] +>"a" : "a" +>"b" : "b" +>"c" : "c" + + identifier: v => v +>identifier : (v: object) => object +>v => v : (v: object) => object +>v : object +>v : object + +}) diff --git a/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.errors.txt new file mode 100644 index 0000000000..7a19c68884 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.errors.txt @@ -0,0 +1,52 @@ +quantifiedTypesIntermediate.ts(14,22): error TS2322: Type 'number' is not assignable to type 'string'. +quantifiedTypesIntermediate.ts(26,22): error TS2322: Type 'number' is not assignable to type 'string'. + + +==== quantifiedTypesIntermediate.ts (2 errors) ==== + type Input = { values: T[], identifier: (value: T) => string } + declare const f: (t: ( Input)[]) => void + + f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + } + ]) + + f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => Number(v.key) + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! related TS6502 quantifiedTypesIntermediate.ts:1:44: The expected type comes from the return type of this signature. + } + ]) + + + f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + }, + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => Number(v.key) + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! related TS6502 quantifiedTypesIntermediate.ts:1:44: The expected type comes from the return type of this signature. + } + ]) + + + f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + }, + { + values: [{ id: 1 }, { id: 2 }, { id: 3 }], + identifier: v => v.id.toString() + } + ]) + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.js b/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.js new file mode 100644 index 0000000000..eb438b6078 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.js @@ -0,0 +1,78 @@ +//// [tests/cases/compiler/quantifiedTypesIntermediate.ts] //// + +//// [quantifiedTypesIntermediate.ts] +type Input = { values: T[], identifier: (value: T) => string } +declare const f: (t: ( Input)[]) => void + +f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + } +]) + +f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => Number(v.key) + } +]) + + +f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + }, + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => Number(v.key) + } +]) + + +f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + }, + { + values: [{ id: 1 }, { id: 2 }, { id: 3 }], + identifier: v => v.id.toString() + } +]) + + +//// [quantifiedTypesIntermediate.js] +f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + } +]); +f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => Number(v.key) + } +]); +f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + }, + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => Number(v.key) + } +]); +f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + }, + { + values: [{ id: 1 }, { id: 2 }, { id: 3 }], + identifier: v => v.id.toString() + } +]); diff --git a/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.symbols b/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.symbols new file mode 100644 index 0000000000..382b53bd89 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.symbols @@ -0,0 +1,127 @@ +//// [tests/cases/compiler/quantifiedTypesIntermediate.ts] //// + +=== quantifiedTypesIntermediate.ts === +type Input = { values: T[], identifier: (value: T) => string } +>Input : Symbol(Input, Decl(quantifiedTypesIntermediate.ts, 0, 0)) +>T : Symbol(T, Decl(quantifiedTypesIntermediate.ts, 0, 11)) +>values : Symbol(values, Decl(quantifiedTypesIntermediate.ts, 0, 17)) +>T : Symbol(T, Decl(quantifiedTypesIntermediate.ts, 0, 11)) +>identifier : Symbol(identifier, Decl(quantifiedTypesIntermediate.ts, 0, 30)) +>value : Symbol(value, Decl(quantifiedTypesIntermediate.ts, 0, 44)) +>T : Symbol(T, Decl(quantifiedTypesIntermediate.ts, 0, 11)) + +declare const f: (t: ( Input)[]) => void +>f : Symbol(f, Decl(quantifiedTypesIntermediate.ts, 1, 13)) +>t : Symbol(t, Decl(quantifiedTypesIntermediate.ts, 1, 18)) +>T : Symbol(T, Decl(quantifiedTypesIntermediate.ts, 1, 23)) +>Input : Symbol(Input, Decl(quantifiedTypesIntermediate.ts, 0, 0)) +>T : Symbol(T, Decl(quantifiedTypesIntermediate.ts, 1, 23)) + +f([ +>f : Symbol(f, Decl(quantifiedTypesIntermediate.ts, 1, 13)) + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : Symbol(values, Decl(quantifiedTypesIntermediate.ts, 4, 3)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 5, 14)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 5, 28)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 5, 42)) + + identifier: v => v.key +>identifier : Symbol(identifier, Decl(quantifiedTypesIntermediate.ts, 5, 55)) +>v : Symbol(v, Decl(quantifiedTypesIntermediate.ts, 6, 15)) +>v.key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 5, 14)) +>v : Symbol(v, Decl(quantifiedTypesIntermediate.ts, 6, 15)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 5, 14)) + } +]) + +f([ +>f : Symbol(f, Decl(quantifiedTypesIntermediate.ts, 1, 13)) + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : Symbol(values, Decl(quantifiedTypesIntermediate.ts, 11, 3)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 12, 14)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 12, 28)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 12, 42)) + + identifier: v => Number(v.key) +>identifier : Symbol(identifier, Decl(quantifiedTypesIntermediate.ts, 12, 55)) +>v : Symbol(v, Decl(quantifiedTypesIntermediate.ts, 13, 15)) +>Number : Symbol(Number, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>v.key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 12, 14)) +>v : Symbol(v, Decl(quantifiedTypesIntermediate.ts, 13, 15)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 12, 14)) + } +]) + + +f([ +>f : Symbol(f, Decl(quantifiedTypesIntermediate.ts, 1, 13)) + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : Symbol(values, Decl(quantifiedTypesIntermediate.ts, 19, 3)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 20, 14)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 20, 28)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 20, 42)) + + identifier: v => v.key +>identifier : Symbol(identifier, Decl(quantifiedTypesIntermediate.ts, 20, 55)) +>v : Symbol(v, Decl(quantifiedTypesIntermediate.ts, 21, 15)) +>v.key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 20, 14)) +>v : Symbol(v, Decl(quantifiedTypesIntermediate.ts, 21, 15)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 20, 14)) + + }, + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : Symbol(values, Decl(quantifiedTypesIntermediate.ts, 23, 3)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 24, 14)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 24, 28)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 24, 42)) + + identifier: v => Number(v.key) +>identifier : Symbol(identifier, Decl(quantifiedTypesIntermediate.ts, 24, 55)) +>v : Symbol(v, Decl(quantifiedTypesIntermediate.ts, 25, 15)) +>Number : Symbol(Number, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>v.key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 24, 14)) +>v : Symbol(v, Decl(quantifiedTypesIntermediate.ts, 25, 15)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 24, 14)) + } +]) + + +f([ +>f : Symbol(f, Decl(quantifiedTypesIntermediate.ts, 1, 13)) + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : Symbol(values, Decl(quantifiedTypesIntermediate.ts, 31, 3)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 32, 14)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 32, 28)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 32, 42)) + + identifier: v => v.key +>identifier : Symbol(identifier, Decl(quantifiedTypesIntermediate.ts, 32, 55)) +>v : Symbol(v, Decl(quantifiedTypesIntermediate.ts, 33, 15)) +>v.key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 32, 14)) +>v : Symbol(v, Decl(quantifiedTypesIntermediate.ts, 33, 15)) +>key : Symbol(key, Decl(quantifiedTypesIntermediate.ts, 32, 14)) + + }, + { + values: [{ id: 1 }, { id: 2 }, { id: 3 }], +>values : Symbol(values, Decl(quantifiedTypesIntermediate.ts, 35, 3)) +>id : Symbol(id, Decl(quantifiedTypesIntermediate.ts, 36, 14)) +>id : Symbol(id, Decl(quantifiedTypesIntermediate.ts, 36, 25)) +>id : Symbol(id, Decl(quantifiedTypesIntermediate.ts, 36, 36)) + + identifier: v => v.id.toString() +>identifier : Symbol(identifier, Decl(quantifiedTypesIntermediate.ts, 36, 46)) +>v : Symbol(v, Decl(quantifiedTypesIntermediate.ts, 37, 15)) +>v.id.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +>v.id : Symbol(id, Decl(quantifiedTypesIntermediate.ts, 36, 14)) +>v : Symbol(v, Decl(quantifiedTypesIntermediate.ts, 37, 15)) +>id : Symbol(id, Decl(quantifiedTypesIntermediate.ts, 36, 14)) +>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) + } +]) + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.types b/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.types new file mode 100644 index 0000000000..3adbdf63e7 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.types @@ -0,0 +1,192 @@ +//// [tests/cases/compiler/quantifiedTypesIntermediate.ts] //// + +=== quantifiedTypesIntermediate.ts === +type Input = { values: T[], identifier: (value: T) => string } +>Input : Input +>values : T[] +>identifier : (value: T) => string +>value : T + +declare const f: (t: ( Input)[]) => void +>f : (t: ( Input)[]) => void +>t : ( Input)[] + +f([ +>f([ { values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => v.key }]) : void +>f : (t: ( Input)[]) => void +>[ { values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => v.key }] : { values: { key: string; }[]; identifier: (v: { key: string; }) => string; }[] + { +>{ values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => v.key } : { values: { key: string; }[]; identifier: (v: { key: string; }) => string; } + + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : { key: string; }[] +>[{ key: "a" }, { key: "b" }, { key: "c" }] : { key: string; }[] +>{ key: "a" } : { key: string; } +>key : string +>"a" : "a" +>{ key: "b" } : { key: string; } +>key : string +>"b" : "b" +>{ key: "c" } : { key: string; } +>key : string +>"c" : "c" + + identifier: v => v.key +>identifier : (v: { key: string; }) => string +>v => v.key : (v: { key: string; }) => string +>v : { key: string; } +>v.key : string +>v : { key: string; } +>key : string + } +]) + +f([ +>f([ { values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => Number(v.key) }]) : void +>f : (t: ( Input)[]) => void +>[ { values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => Number(v.key) }] : any[] + { +>{ values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => Number(v.key) } : any + + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : { key: string; }[] +>[{ key: "a" }, { key: "b" }, { key: "c" }] : { key: string; }[] +>{ key: "a" } : { key: string; } +>key : string +>"a" : "a" +>{ key: "b" } : { key: string; } +>key : string +>"b" : "b" +>{ key: "c" } : { key: string; } +>key : string +>"c" : "c" + + identifier: v => Number(v.key) +>identifier : (v: { key: string; }) => number +>v => Number(v.key) : (v: { key: string; }) => number +>v : { key: string; } +>Number(v.key) : number +>Number : NumberConstructor +>v.key : string +>v : { key: string; } +>key : string + } +]) + + +f([ +>f([ { values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => v.key }, { values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => Number(v.key) }]) : void +>f : (t: ( Input)[]) => void +>[ { values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => v.key }, { values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => Number(v.key) }] : any[] + { +>{ values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => v.key } : { values: { key: string; }[]; identifier: (v: { key: string; }) => string; } + + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : { key: string; }[] +>[{ key: "a" }, { key: "b" }, { key: "c" }] : { key: string; }[] +>{ key: "a" } : { key: string; } +>key : string +>"a" : "a" +>{ key: "b" } : { key: string; } +>key : string +>"b" : "b" +>{ key: "c" } : { key: string; } +>key : string +>"c" : "c" + + identifier: v => v.key +>identifier : (v: { key: string; }) => string +>v => v.key : (v: { key: string; }) => string +>v : { key: string; } +>v.key : string +>v : { key: string; } +>key : string + + }, + { +>{ values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => Number(v.key) } : any + + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : { key: string; }[] +>[{ key: "a" }, { key: "b" }, { key: "c" }] : { key: string; }[] +>{ key: "a" } : { key: string; } +>key : string +>"a" : "a" +>{ key: "b" } : { key: string; } +>key : string +>"b" : "b" +>{ key: "c" } : { key: string; } +>key : string +>"c" : "c" + + identifier: v => Number(v.key) +>identifier : (v: { key: string; }) => number +>v => Number(v.key) : (v: { key: string; }) => number +>v : { key: string; } +>Number(v.key) : number +>Number : NumberConstructor +>v.key : string +>v : { key: string; } +>key : string + } +]) + + +f([ +>f([ { values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => v.key }, { values: [{ id: 1 }, { id: 2 }, { id: 3 }], identifier: v => v.id.toString() }]) : void +>f : (t: ( Input)[]) => void +>[ { values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => v.key }, { values: [{ id: 1 }, { id: 2 }, { id: 3 }], identifier: v => v.id.toString() }] : ({ values: { key: string; }[]; identifier: (v: { key: string; }) => string; } | { values: { id: number; }[]; identifier: (v: { id: number; }) => string; })[] + { +>{ values: [{ key: "a" }, { key: "b" }, { key: "c" }], identifier: v => v.key } : { values: { key: string; }[]; identifier: (v: { key: string; }) => string; } + + values: [{ key: "a" }, { key: "b" }, { key: "c" }], +>values : { key: string; }[] +>[{ key: "a" }, { key: "b" }, { key: "c" }] : { key: string; }[] +>{ key: "a" } : { key: string; } +>key : string +>"a" : "a" +>{ key: "b" } : { key: string; } +>key : string +>"b" : "b" +>{ key: "c" } : { key: string; } +>key : string +>"c" : "c" + + identifier: v => v.key +>identifier : (v: { key: string; }) => string +>v => v.key : (v: { key: string; }) => string +>v : { key: string; } +>v.key : string +>v : { key: string; } +>key : string + + }, + { +>{ values: [{ id: 1 }, { id: 2 }, { id: 3 }], identifier: v => v.id.toString() } : { values: { id: number; }[]; identifier: (v: { id: number; }) => string; } + + values: [{ id: 1 }, { id: 2 }, { id: 3 }], +>values : { id: number; }[] +>[{ id: 1 }, { id: 2 }, { id: 3 }] : { id: number; }[] +>{ id: 1 } : { id: number; } +>id : number +>1 : 1 +>{ id: 2 } : { id: number; } +>id : number +>2 : 2 +>{ id: 3 } : { id: number; } +>id : number +>3 : 3 + + identifier: v => v.id.toString() +>identifier : (v: { id: number; }) => string +>v => v.id.toString() : (v: { id: number; }) => string +>v : { id: number; } +>v.id.toString() : string +>v.id.toString : (radix?: number) => string +>v.id : number +>v : { id: number; } +>id : number +>toString : (radix?: number) => string + } +]) + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesNormalizedShapes.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesNormalizedShapes.errors.txt new file mode 100644 index 0000000000..49820d3d45 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesNormalizedShapes.errors.txt @@ -0,0 +1,26 @@ +quantifiedTypesNormalizedShapes.ts(15,5): error TS2322: Type '"a"' is not assignable to type '"b"'. + + +==== quantifiedTypesNormalizedShapes.ts (1 errors) ==== + type NormalizedRecord = + { [K in Id]: Omit & { id: K } } + + interface Layer { + id: string + color: string + } + + let layers: NormalizedRecord = { + a: { + id: "a", + color: "green" + }, + b: { + id: "a", // should have been "b" + ~~ +!!! error TS2322: Type '"a"' is not assignable to type '"b"'. +!!! related TS6500 quantifiedTypesNormalizedShapes.ts:2:54: The expected type comes from property 'id' which is declared here on type 'Omit & { id: "b"; }' + color: "blue" + } + } + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesNormalizedShapes.js b/testdata/baselines/reference/compiler/quantifiedTypesNormalizedShapes.js new file mode 100644 index 0000000000..a0bc31d741 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesNormalizedShapes.js @@ -0,0 +1,34 @@ +//// [tests/cases/compiler/quantifiedTypesNormalizedShapes.ts] //// + +//// [quantifiedTypesNormalizedShapes.ts] +type NormalizedRecord = + { [K in Id]: Omit & { id: K } } + +interface Layer { + id: string + color: string +} + +let layers: NormalizedRecord = { + a: { + id: "a", + color: "green" + }, + b: { + id: "a", // should have been "b" + color: "blue" + } +} + + +//// [quantifiedTypesNormalizedShapes.js] +let layers = { + a: { + id: "a", + color: "green" + }, + b: { + id: "a", // should have been "b" + color: "blue" + } +}; diff --git a/testdata/baselines/reference/compiler/quantifiedTypesNormalizedShapes.symbols b/testdata/baselines/reference/compiler/quantifiedTypesNormalizedShapes.symbols new file mode 100644 index 0000000000..1ff71c460c --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesNormalizedShapes.symbols @@ -0,0 +1,53 @@ +//// [tests/cases/compiler/quantifiedTypesNormalizedShapes.ts] //// + +=== quantifiedTypesNormalizedShapes.ts === +type NormalizedRecord = +>NormalizedRecord : Symbol(NormalizedRecord, Decl(quantifiedTypesNormalizedShapes.ts, 0, 0)) +>T : Symbol(T, Decl(quantifiedTypesNormalizedShapes.ts, 0, 22)) +>id : Symbol(id, Decl(quantifiedTypesNormalizedShapes.ts, 0, 33)) + + { [K in Id]: Omit & { id: K } } +>Id : Symbol(Id, Decl(quantifiedTypesNormalizedShapes.ts, 1, 3)) +>K : Symbol(K, Decl(quantifiedTypesNormalizedShapes.ts, 1, 25)) +>Id : Symbol(Id, Decl(quantifiedTypesNormalizedShapes.ts, 1, 3)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(quantifiedTypesNormalizedShapes.ts, 0, 22)) +>id : Symbol(id, Decl(quantifiedTypesNormalizedShapes.ts, 1, 52)) +>K : Symbol(K, Decl(quantifiedTypesNormalizedShapes.ts, 1, 25)) + +interface Layer { +>Layer : Symbol(Layer, Decl(quantifiedTypesNormalizedShapes.ts, 1, 62)) + + id: string +>id : Symbol(Layer.id, Decl(quantifiedTypesNormalizedShapes.ts, 3, 17)) + + color: string +>color : Symbol(Layer.color, Decl(quantifiedTypesNormalizedShapes.ts, 4, 12)) +} + +let layers: NormalizedRecord = { +>layers : Symbol(layers, Decl(quantifiedTypesNormalizedShapes.ts, 8, 3)) +>NormalizedRecord : Symbol(NormalizedRecord, Decl(quantifiedTypesNormalizedShapes.ts, 0, 0)) +>Layer : Symbol(Layer, Decl(quantifiedTypesNormalizedShapes.ts, 1, 62)) + + a: { +>a : Symbol(a, Decl(quantifiedTypesNormalizedShapes.ts, 8, 39)) + + id: "a", +>id : Symbol(id, Decl(quantifiedTypesNormalizedShapes.ts, 9, 6)) + + color: "green" +>color : Symbol(color, Decl(quantifiedTypesNormalizedShapes.ts, 10, 12)) + + }, + b: { +>b : Symbol(b, Decl(quantifiedTypesNormalizedShapes.ts, 12, 4)) + + id: "a", // should have been "b" +>id : Symbol(id, Decl(quantifiedTypesNormalizedShapes.ts, 13, 6)) + + color: "blue" +>color : Symbol(color, Decl(quantifiedTypesNormalizedShapes.ts, 14, 12)) + } +} + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesNormalizedShapes.types b/testdata/baselines/reference/compiler/quantifiedTypesNormalizedShapes.types new file mode 100644 index 0000000000..a056d39039 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesNormalizedShapes.types @@ -0,0 +1,49 @@ +//// [tests/cases/compiler/quantifiedTypesNormalizedShapes.ts] //// + +=== quantifiedTypesNormalizedShapes.ts === +type NormalizedRecord = +>NormalizedRecord : { [K in Id]: Omit & { id: K; }; } +>id : string + + { [K in Id]: Omit & { id: K } } +>id : K + +interface Layer { + id: string +>id : string + + color: string +>color : string +} + +let layers: NormalizedRecord = { +>layers : { [K in Id]: Omit & { id: K; }; } +>{ a: { id: "a", color: "green" }, b: { id: "a", // should have been "b" color: "blue" }} : any + + a: { +>a : { id: string; color: string; } +>{ id: "a", color: "green" } : { id: string; color: string; } + + id: "a", +>id : string +>"a" : "a" + + color: "green" +>color : string +>"green" : "green" + + }, + b: { +>b : { id: string; color: string; } +>{ id: "a", // should have been "b" color: "blue" } : { id: string; color: string; } + + id: "a", // should have been "b" +>id : string +>"a" : "a" + + color: "blue" +>color : string +>"blue" : "blue" + } +} + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext.js b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext.js new file mode 100644 index 0000000000..3a786df798 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext.js @@ -0,0 +1,9 @@ +//// [tests/cases/compiler/quantifiedTypesParentInferenceContext.ts] //// + +//// [quantifiedTypesParentInferenceContext.ts] +declare const f: (a: A, f: [(a: A) => void]) => void +f(0, [a => {}]) + + +//// [quantifiedTypesParentInferenceContext.js] +f(0, [a => { }]); diff --git a/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext.symbols b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext.symbols new file mode 100644 index 0000000000..0a7a9c737a --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext.symbols @@ -0,0 +1,17 @@ +//// [tests/cases/compiler/quantifiedTypesParentInferenceContext.ts] //// + +=== quantifiedTypesParentInferenceContext.ts === +declare const f: (a: A, f: [(a: A) => void]) => void +>f : Symbol(f, Decl(quantifiedTypesParentInferenceContext.ts, 0, 13)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext.ts, 0, 18)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext.ts, 0, 21)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext.ts, 0, 18)) +>f : Symbol(f, Decl(quantifiedTypesParentInferenceContext.ts, 0, 26)) +>T : Symbol(T, Decl(quantifiedTypesParentInferenceContext.ts, 0, 31)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext.ts, 0, 36)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext.ts, 0, 18)) + +f(0, [a => {}]) +>f : Symbol(f, Decl(quantifiedTypesParentInferenceContext.ts, 0, 13)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext.ts, 1, 6)) + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext.types b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext.types new file mode 100644 index 0000000000..4dd5c97fed --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext.types @@ -0,0 +1,17 @@ +//// [tests/cases/compiler/quantifiedTypesParentInferenceContext.ts] //// + +=== quantifiedTypesParentInferenceContext.ts === +declare const f: (a: A, f: [(a: A) => void]) => void +>f : (a: A, f: [(a: A) => void]) => void +>a : A +>f : [(a: A) => void] +>a : A + +f(0, [a => {}]) +>f(0, [a => {}]) : void +>f : (a: A, f: [(a: A) => void]) => void +>0 : 0 +>[a => {}] : [(a: number) => void] +>a => {} : (a: number) => void +>a : number + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext2.js b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext2.js new file mode 100644 index 0000000000..298ef12633 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext2.js @@ -0,0 +1,8 @@ +//// [tests/cases/compiler/quantifiedTypesParentInferenceContext2.ts] //// + +//// [quantifiedTypesParentInferenceContext2.ts] +declare const f: (a: A, f: [ ((a: A) => void)]) => void +f(0, [a => {}]) + +//// [quantifiedTypesParentInferenceContext2.js] +f(0, [a => { }]); diff --git a/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext2.symbols b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext2.symbols new file mode 100644 index 0000000000..b65ea49e8b --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext2.symbols @@ -0,0 +1,17 @@ +//// [tests/cases/compiler/quantifiedTypesParentInferenceContext2.ts] //// + +=== quantifiedTypesParentInferenceContext2.ts === +declare const f: (a: A, f: [ ((a: A) => void)]) => void +>f : Symbol(f, Decl(quantifiedTypesParentInferenceContext2.ts, 0, 13)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext2.ts, 0, 18)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext2.ts, 0, 21)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext2.ts, 0, 18)) +>f : Symbol(f, Decl(quantifiedTypesParentInferenceContext2.ts, 0, 26)) +>T : Symbol(T, Decl(quantifiedTypesParentInferenceContext2.ts, 0, 32)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext2.ts, 0, 37)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext2.ts, 0, 18)) + +f(0, [a => {}]) +>f : Symbol(f, Decl(quantifiedTypesParentInferenceContext2.ts, 0, 13)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext2.ts, 1, 6)) + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext2.types b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext2.types new file mode 100644 index 0000000000..2ce8c87df1 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext2.types @@ -0,0 +1,17 @@ +//// [tests/cases/compiler/quantifiedTypesParentInferenceContext2.ts] //// + +=== quantifiedTypesParentInferenceContext2.ts === +declare const f: (a: A, f: [ ((a: A) => void)]) => void +>f : (a: A, f: [ (a: A) => void]) => void +>a : A +>f : [ (a: A) => void] +>a : A + +f(0, [a => {}]) +>f(0, [a => {}]) : void +>f : (a: A, f: [ (a: A) => void]) => void +>0 : 0 +>[a => {}] : [(a: number) => void] +>a => {} : (a: number) => void +>a : number + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext3.js b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext3.js new file mode 100644 index 0000000000..bf2cb764c7 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext3.js @@ -0,0 +1,9 @@ +//// [tests/cases/compiler/quantifiedTypesParentInferenceContext3.ts] //// + +//// [quantifiedTypesParentInferenceContext3.ts] +declare const f: (x: { a: A, f: [ ((a: A) => void)] }) => void +f({ a: 0, f: [a => { a satisfies number; }] }) + + +//// [quantifiedTypesParentInferenceContext3.js] +f({ a: 0, f: [a => { a; }] }); diff --git a/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext3.symbols b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext3.symbols new file mode 100644 index 0000000000..ab66b8caf4 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext3.symbols @@ -0,0 +1,21 @@ +//// [tests/cases/compiler/quantifiedTypesParentInferenceContext3.ts] //// + +=== quantifiedTypesParentInferenceContext3.ts === +declare const f: (x: { a: A, f: [ ((a: A) => void)] }) => void +>f : Symbol(f, Decl(quantifiedTypesParentInferenceContext3.ts, 0, 13)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext3.ts, 0, 18)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext3.ts, 0, 21)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext3.ts, 0, 25)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext3.ts, 0, 18)) +>f : Symbol(f, Decl(quantifiedTypesParentInferenceContext3.ts, 0, 31)) +>T : Symbol(T, Decl(quantifiedTypesParentInferenceContext3.ts, 0, 37)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext3.ts, 0, 42)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext3.ts, 0, 18)) + +f({ a: 0, f: [a => { a satisfies number; }] }) +>f : Symbol(f, Decl(quantifiedTypesParentInferenceContext3.ts, 0, 13)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext3.ts, 1, 3)) +>f : Symbol(f, Decl(quantifiedTypesParentInferenceContext3.ts, 1, 9)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext3.ts, 1, 14)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext3.ts, 1, 14)) + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext3.types b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext3.types new file mode 100644 index 0000000000..e9cc9744c5 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext3.types @@ -0,0 +1,23 @@ +//// [tests/cases/compiler/quantifiedTypesParentInferenceContext3.ts] //// + +=== quantifiedTypesParentInferenceContext3.ts === +declare const f: (x: { a: A, f: [ ((a: A) => void)] }) => void +>f : (x: { a: A; f: [ (a: A) => void]; }) => void +>x : { a: A; f: [ (a: A) => void]; } +>a : A +>f : [ (a: A) => void] +>a : A + +f({ a: 0, f: [a => { a satisfies number; }] }) +>f({ a: 0, f: [a => { a satisfies number; }] }) : void +>f : (x: { a: A; f: [ (a: A) => void]; }) => void +>{ a: 0, f: [a => { a satisfies number; }] } : { a: number; f: [(a: number) => void]; } +>a : number +>0 : 0 +>f : [(a: number) => void] +>[a => { a satisfies number; }] : [(a: number) => void] +>a => { a satisfies number; } : (a: number) => void +>a : number +>a satisfies number : number +>a : number + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.errors.txt new file mode 100644 index 0000000000..ddc1590c26 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.errors.txt @@ -0,0 +1,93 @@ +quantifiedTypesReduxToolkit.ts(63,7): error TS2322: Type '(state: { foo: string; }, action: PayloadAction) => void' is not assignable to type '(state: { foo: string; }, action: { payload: number; } & { type: "invalidReducerWithPrepareNotation"; }) => void'. + Types of parameters 'action' and 'action' are incompatible. + Type '{ payload: number; } & { type: "invalidReducerWithPrepareNotation"; }' is not assignable to type 'PayloadAction'. + Types of property 'payload' are incompatible. + Type 'number' is not assignable to type 'string'. + + +==== quantifiedTypesReduxToolkit.ts (1 errors) ==== + // https://github.com/microsoft/TypeScript/issues/51612#issuecomment-1375431039 + + declare const createSlice: + < S extends object + , Rs extends { [T1 in T]:

Reducer } + > + (slice: { + name: string, + initialState: S, + reducers: Rs + }) => + Slice + + type Reducer = + | ((state: S, action: P & { type: T }) => void) + | { reducer: (state: S, action: P & { type: T }) => void + , prepare: (...a: never) => P + } + + type Slice = + { actions: + { [K in keyof Rs]: + Rs[K] extends { prepare: (...a: infer A) => infer R } ? (...a: A) => { type: K } & R : + Rs[K] extends (state: never, action: PayloadAction) => unknown ? (payload: P) => { type: K, payload: P } : + never + } + } + + type PayloadAction

= + { type: string + , payload: P + } + + const slice = createSlice({ + name: "someSlice", + initialState: { + foo: "bar" + }, + reducers: { + simpleReducer: (state, action: PayloadAction) => { + state.foo = action.payload + }, + reducerWithPrepareNotation: { + prepare: (char: string, repeats: number) => { + return { payload: char.repeat(repeats), extraStuff: true } + }, + reducer: (state, action) => { + state.foo = action.payload + } + }, + reducerWithAnotherPrepareNotation: { + prepare: (char: string, repeats: number) => { + return { payload: repeats * char.length } + }, + reducer: (state, action) => { + state.foo = state.foo.slice(0, action.payload) + }, + }, + invalidReducerWithPrepareNotation: { + prepare: (char: string, repeats: number) => { + return { payload: repeats * char.length } + }, + reducer: (state, action: PayloadAction) => { + ~~~~~~~ +!!! error TS2322: Type '(state: { foo: string; }, action: PayloadAction) => void' is not assignable to type '(state: { foo: string; }, action: { payload: number; } & { type: "invalidReducerWithPrepareNotation"; }) => void'. +!!! error TS2322: Types of parameters 'action' and 'action' are incompatible. +!!! error TS2322: Type '{ payload: number; } & { type: "invalidReducerWithPrepareNotation"; }' is not assignable to type 'PayloadAction'. +!!! error TS2322: Types of property 'payload' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + state.foo = action.payload + }, + }, + } + }) + + { + const _expectType: (payload: string) => PayloadAction = slice.actions.simpleReducer + } + { + const _expectType: (char: string, repeats: number) => PayloadAction = slice.actions.reducerWithPrepareNotation + } + { + const _expectType: (char: string, repeats: number) => PayloadAction = slice.actions.reducerWithAnotherPrepareNotation + } + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.js b/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.js new file mode 100644 index 0000000000..0f1d6da794 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.js @@ -0,0 +1,129 @@ +//// [tests/cases/compiler/quantifiedTypesReduxToolkit.ts] //// + +//// [quantifiedTypesReduxToolkit.ts] +// https://github.com/microsoft/TypeScript/issues/51612#issuecomment-1375431039 + +declare const createSlice: + < S extends object + , Rs extends { [T1 in T]:

Reducer } + > + (slice: { + name: string, + initialState: S, + reducers: Rs + }) => + Slice + +type Reducer = + | ((state: S, action: P & { type: T }) => void) + | { reducer: (state: S, action: P & { type: T }) => void + , prepare: (...a: never) => P + } + +type Slice = + { actions: + { [K in keyof Rs]: + Rs[K] extends { prepare: (...a: infer A) => infer R } ? (...a: A) => { type: K } & R : + Rs[K] extends (state: never, action: PayloadAction) => unknown ? (payload: P) => { type: K, payload: P } : + never + } + } + +type PayloadAction

= + { type: string + , payload: P + } + +const slice = createSlice({ + name: "someSlice", + initialState: { + foo: "bar" + }, + reducers: { + simpleReducer: (state, action: PayloadAction) => { + state.foo = action.payload + }, + reducerWithPrepareNotation: { + prepare: (char: string, repeats: number) => { + return { payload: char.repeat(repeats), extraStuff: true } + }, + reducer: (state, action) => { + state.foo = action.payload + } + }, + reducerWithAnotherPrepareNotation: { + prepare: (char: string, repeats: number) => { + return { payload: repeats * char.length } + }, + reducer: (state, action) => { + state.foo = state.foo.slice(0, action.payload) + }, + }, + invalidReducerWithPrepareNotation: { + prepare: (char: string, repeats: number) => { + return { payload: repeats * char.length } + }, + reducer: (state, action: PayloadAction) => { + state.foo = action.payload + }, + }, + } +}) + +{ + const _expectType: (payload: string) => PayloadAction = slice.actions.simpleReducer +} +{ + const _expectType: (char: string, repeats: number) => PayloadAction = slice.actions.reducerWithPrepareNotation +} +{ + const _expectType: (char: string, repeats: number) => PayloadAction = slice.actions.reducerWithAnotherPrepareNotation +} + + +//// [quantifiedTypesReduxToolkit.js] +// https://github.com/microsoft/TypeScript/issues/51612#issuecomment-1375431039 +const slice = createSlice({ + name: "someSlice", + initialState: { + foo: "bar" + }, + reducers: { + simpleReducer: (state, action) => { + state.foo = action.payload; + }, + reducerWithPrepareNotation: { + prepare: (char, repeats) => { + return { payload: char.repeat(repeats), extraStuff: true }; + }, + reducer: (state, action) => { + state.foo = action.payload; + } + }, + reducerWithAnotherPrepareNotation: { + prepare: (char, repeats) => { + return { payload: repeats * char.length }; + }, + reducer: (state, action) => { + state.foo = state.foo.slice(0, action.payload); + }, + }, + invalidReducerWithPrepareNotation: { + prepare: (char, repeats) => { + return { payload: repeats * char.length }; + }, + reducer: (state, action) => { + state.foo = action.payload; + }, + }, + } +}); +{ + const _expectType = slice.actions.simpleReducer; +} +{ + const _expectType = slice.actions.reducerWithPrepareNotation; +} +{ + const _expectType = slice.actions.reducerWithAnotherPrepareNotation; +} diff --git a/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.symbols b/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.symbols new file mode 100644 index 0000000000..66f3d99d61 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.symbols @@ -0,0 +1,297 @@ +//// [tests/cases/compiler/quantifiedTypesReduxToolkit.ts] //// + +=== quantifiedTypesReduxToolkit.ts === +// https://github.com/microsoft/TypeScript/issues/51612#issuecomment-1375431039 + +declare const createSlice: +>createSlice : Symbol(createSlice, Decl(quantifiedTypesReduxToolkit.ts, 2, 13)) + + < S extends object +>S : Symbol(S, Decl(quantifiedTypesReduxToolkit.ts, 3, 3)) + + , Rs extends { [T1 in T]:

Reducer } +>Rs : Symbol(Rs, Decl(quantifiedTypesReduxToolkit.ts, 4, 3)) +>T : Symbol(T, Decl(quantifiedTypesReduxToolkit.ts, 4, 16)) +>T1 : Symbol(T1, Decl(quantifiedTypesReduxToolkit.ts, 4, 37)) +>T : Symbol(T, Decl(quantifiedTypesReduxToolkit.ts, 4, 16)) +>P : Symbol(P, Decl(quantifiedTypesReduxToolkit.ts, 4, 48)) +>Reducer : Symbol(Reducer, Decl(quantifiedTypesReduxToolkit.ts, 11, 18)) +>S : Symbol(S, Decl(quantifiedTypesReduxToolkit.ts, 3, 3)) +>T1 : Symbol(T1, Decl(quantifiedTypesReduxToolkit.ts, 4, 37)) +>P : Symbol(P, Decl(quantifiedTypesReduxToolkit.ts, 4, 48)) + + > + (slice: { +>slice : Symbol(slice, Decl(quantifiedTypesReduxToolkit.ts, 6, 5)) + + name: string, +>name : Symbol(name, Decl(quantifiedTypesReduxToolkit.ts, 6, 13)) + + initialState: S, +>initialState : Symbol(initialState, Decl(quantifiedTypesReduxToolkit.ts, 7, 19)) +>S : Symbol(S, Decl(quantifiedTypesReduxToolkit.ts, 3, 3)) + + reducers: Rs +>reducers : Symbol(reducers, Decl(quantifiedTypesReduxToolkit.ts, 8, 22)) +>Rs : Symbol(Rs, Decl(quantifiedTypesReduxToolkit.ts, 4, 3)) + + }) => + Slice +>Slice : Symbol(Slice, Decl(quantifiedTypesReduxToolkit.ts, 17, 5)) +>S : Symbol(S, Decl(quantifiedTypesReduxToolkit.ts, 3, 3)) +>Rs : Symbol(Rs, Decl(quantifiedTypesReduxToolkit.ts, 4, 3)) + +type Reducer = +>Reducer : Symbol(Reducer, Decl(quantifiedTypesReduxToolkit.ts, 11, 18)) +>S : Symbol(S, Decl(quantifiedTypesReduxToolkit.ts, 13, 13)) +>T : Symbol(T, Decl(quantifiedTypesReduxToolkit.ts, 13, 15)) +>P : Symbol(P, Decl(quantifiedTypesReduxToolkit.ts, 13, 18)) + + | ((state: S, action: P & { type: T }) => void) +>state : Symbol(state, Decl(quantifiedTypesReduxToolkit.ts, 14, 6)) +>S : Symbol(S, Decl(quantifiedTypesReduxToolkit.ts, 13, 13)) +>action : Symbol(action, Decl(quantifiedTypesReduxToolkit.ts, 14, 15)) +>P : Symbol(P, Decl(quantifiedTypesReduxToolkit.ts, 13, 18)) +>type : Symbol(type, Decl(quantifiedTypesReduxToolkit.ts, 14, 29)) +>T : Symbol(T, Decl(quantifiedTypesReduxToolkit.ts, 13, 15)) + + | { reducer: (state: S, action: P & { type: T }) => void +>reducer : Symbol(reducer, Decl(quantifiedTypesReduxToolkit.ts, 15, 5)) +>state : Symbol(state, Decl(quantifiedTypesReduxToolkit.ts, 15, 16)) +>S : Symbol(S, Decl(quantifiedTypesReduxToolkit.ts, 13, 13)) +>action : Symbol(action, Decl(quantifiedTypesReduxToolkit.ts, 15, 25)) +>P : Symbol(P, Decl(quantifiedTypesReduxToolkit.ts, 13, 18)) +>type : Symbol(type, Decl(quantifiedTypesReduxToolkit.ts, 15, 39)) +>T : Symbol(T, Decl(quantifiedTypesReduxToolkit.ts, 13, 15)) + + , prepare: (...a: never) => P +>prepare : Symbol(prepare, Decl(quantifiedTypesReduxToolkit.ts, 16, 5)) +>a : Symbol(a, Decl(quantifiedTypesReduxToolkit.ts, 16, 16)) +>P : Symbol(P, Decl(quantifiedTypesReduxToolkit.ts, 13, 18)) + } + +type Slice = +>Slice : Symbol(Slice, Decl(quantifiedTypesReduxToolkit.ts, 17, 5)) +>S : Symbol(S, Decl(quantifiedTypesReduxToolkit.ts, 19, 11)) +>Rs : Symbol(Rs, Decl(quantifiedTypesReduxToolkit.ts, 19, 13)) + + { actions: +>actions : Symbol(actions, Decl(quantifiedTypesReduxToolkit.ts, 20, 3)) + + { [K in keyof Rs]: +>K : Symbol(K, Decl(quantifiedTypesReduxToolkit.ts, 21, 9)) +>Rs : Symbol(Rs, Decl(quantifiedTypesReduxToolkit.ts, 19, 13)) + + Rs[K] extends { prepare: (...a: infer A) => infer R } ? (...a: A) => { type: K } & R : +>Rs : Symbol(Rs, Decl(quantifiedTypesReduxToolkit.ts, 19, 13)) +>K : Symbol(K, Decl(quantifiedTypesReduxToolkit.ts, 21, 9)) +>prepare : Symbol(prepare, Decl(quantifiedTypesReduxToolkit.ts, 22, 25)) +>a : Symbol(a, Decl(quantifiedTypesReduxToolkit.ts, 22, 36)) +>A : Symbol(A, Decl(quantifiedTypesReduxToolkit.ts, 22, 47)) +>R : Symbol(R, Decl(quantifiedTypesReduxToolkit.ts, 22, 59)) +>a : Symbol(a, Decl(quantifiedTypesReduxToolkit.ts, 22, 67)) +>A : Symbol(A, Decl(quantifiedTypesReduxToolkit.ts, 22, 47)) +>type : Symbol(type, Decl(quantifiedTypesReduxToolkit.ts, 22, 80)) +>K : Symbol(K, Decl(quantifiedTypesReduxToolkit.ts, 21, 9)) +>R : Symbol(R, Decl(quantifiedTypesReduxToolkit.ts, 22, 59)) + + Rs[K] extends (state: never, action: PayloadAction) => unknown ? (payload: P) => { type: K, payload: P } : +>Rs : Symbol(Rs, Decl(quantifiedTypesReduxToolkit.ts, 19, 13)) +>K : Symbol(K, Decl(quantifiedTypesReduxToolkit.ts, 21, 9)) +>state : Symbol(state, Decl(quantifiedTypesReduxToolkit.ts, 23, 25)) +>action : Symbol(action, Decl(quantifiedTypesReduxToolkit.ts, 23, 38)) +>PayloadAction : Symbol(PayloadAction, Decl(quantifiedTypesReduxToolkit.ts, 26, 3)) +>P : Symbol(P, Decl(quantifiedTypesReduxToolkit.ts, 23, 66)) +>payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 23, 85)) +>P : Symbol(P, Decl(quantifiedTypesReduxToolkit.ts, 23, 66)) +>type : Symbol(type, Decl(quantifiedTypesReduxToolkit.ts, 23, 101)) +>K : Symbol(K, Decl(quantifiedTypesReduxToolkit.ts, 21, 9)) +>payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 23, 110)) +>P : Symbol(P, Decl(quantifiedTypesReduxToolkit.ts, 23, 66)) + + never + } + } + +type PayloadAction

= +>PayloadAction : Symbol(PayloadAction, Decl(quantifiedTypesReduxToolkit.ts, 26, 3)) +>P : Symbol(P, Decl(quantifiedTypesReduxToolkit.ts, 28, 19)) + + { type: string +>type : Symbol(type, Decl(quantifiedTypesReduxToolkit.ts, 29, 3)) + + , payload: P +>payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 30, 3)) +>P : Symbol(P, Decl(quantifiedTypesReduxToolkit.ts, 28, 19)) + } + +const slice = createSlice({ +>slice : Symbol(slice, Decl(quantifiedTypesReduxToolkit.ts, 33, 5)) +>createSlice : Symbol(createSlice, Decl(quantifiedTypesReduxToolkit.ts, 2, 13)) + + name: "someSlice", +>name : Symbol(name, Decl(quantifiedTypesReduxToolkit.ts, 33, 27)) + + initialState: { +>initialState : Symbol(initialState, Decl(quantifiedTypesReduxToolkit.ts, 34, 20)) + + foo: "bar" +>foo : Symbol(foo, Decl(quantifiedTypesReduxToolkit.ts, 35, 17)) + + }, + reducers: { +>reducers : Symbol(reducers, Decl(quantifiedTypesReduxToolkit.ts, 37, 4)) + + simpleReducer: (state, action: PayloadAction) => { +>simpleReducer : Symbol(simpleReducer, Decl(quantifiedTypesReduxToolkit.ts, 38, 13)) +>state : Symbol(state, Decl(quantifiedTypesReduxToolkit.ts, 39, 20)) +>action : Symbol(action, Decl(quantifiedTypesReduxToolkit.ts, 39, 26)) +>PayloadAction : Symbol(PayloadAction, Decl(quantifiedTypesReduxToolkit.ts, 26, 3)) + + state.foo = action.payload +>state.foo : Symbol(foo, Decl(quantifiedTypesReduxToolkit.ts, 35, 17)) +>state : Symbol(state, Decl(quantifiedTypesReduxToolkit.ts, 39, 20)) +>foo : Symbol(foo, Decl(quantifiedTypesReduxToolkit.ts, 35, 17)) +>action.payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 30, 3)) +>action : Symbol(action, Decl(quantifiedTypesReduxToolkit.ts, 39, 26)) +>payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 30, 3)) + + }, + reducerWithPrepareNotation: { +>reducerWithPrepareNotation : Symbol(reducerWithPrepareNotation, Decl(quantifiedTypesReduxToolkit.ts, 41, 6)) + + prepare: (char: string, repeats: number) => { +>prepare : Symbol(prepare, Decl(quantifiedTypesReduxToolkit.ts, 42, 33)) +>char : Symbol(char, Decl(quantifiedTypesReduxToolkit.ts, 43, 16)) +>repeats : Symbol(repeats, Decl(quantifiedTypesReduxToolkit.ts, 43, 29)) + + return { payload: char.repeat(repeats), extraStuff: true } +>payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 44, 16)) +>char.repeat : Symbol(String.repeat, Decl(lib.es2015.core.d.ts, --, --)) +>char : Symbol(char, Decl(quantifiedTypesReduxToolkit.ts, 43, 16)) +>repeat : Symbol(String.repeat, Decl(lib.es2015.core.d.ts, --, --)) +>repeats : Symbol(repeats, Decl(quantifiedTypesReduxToolkit.ts, 43, 29)) +>extraStuff : Symbol(extraStuff, Decl(quantifiedTypesReduxToolkit.ts, 44, 47)) + + }, + reducer: (state, action) => { +>reducer : Symbol(reducer, Decl(quantifiedTypesReduxToolkit.ts, 45, 8)) +>state : Symbol(state, Decl(quantifiedTypesReduxToolkit.ts, 46, 16)) +>action : Symbol(action, Decl(quantifiedTypesReduxToolkit.ts, 46, 22)) + + state.foo = action.payload +>state.foo : Symbol(foo, Decl(quantifiedTypesReduxToolkit.ts, 35, 17)) +>state : Symbol(state, Decl(quantifiedTypesReduxToolkit.ts, 46, 16)) +>foo : Symbol(foo, Decl(quantifiedTypesReduxToolkit.ts, 35, 17)) +>action.payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 44, 16)) +>action : Symbol(action, Decl(quantifiedTypesReduxToolkit.ts, 46, 22)) +>payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 44, 16)) + } + }, + reducerWithAnotherPrepareNotation: { +>reducerWithAnotherPrepareNotation : Symbol(reducerWithAnotherPrepareNotation, Decl(quantifiedTypesReduxToolkit.ts, 49, 6)) + + prepare: (char: string, repeats: number) => { +>prepare : Symbol(prepare, Decl(quantifiedTypesReduxToolkit.ts, 50, 40)) +>char : Symbol(char, Decl(quantifiedTypesReduxToolkit.ts, 51, 16)) +>repeats : Symbol(repeats, Decl(quantifiedTypesReduxToolkit.ts, 51, 29)) + + return { payload: repeats * char.length } +>payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 52, 16)) +>repeats : Symbol(repeats, Decl(quantifiedTypesReduxToolkit.ts, 51, 29)) +>char.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) +>char : Symbol(char, Decl(quantifiedTypesReduxToolkit.ts, 51, 16)) +>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) + + }, + reducer: (state, action) => { +>reducer : Symbol(reducer, Decl(quantifiedTypesReduxToolkit.ts, 53, 8)) +>state : Symbol(state, Decl(quantifiedTypesReduxToolkit.ts, 54, 16)) +>action : Symbol(action, Decl(quantifiedTypesReduxToolkit.ts, 54, 22)) + + state.foo = state.foo.slice(0, action.payload) +>state.foo : Symbol(foo, Decl(quantifiedTypesReduxToolkit.ts, 35, 17)) +>state : Symbol(state, Decl(quantifiedTypesReduxToolkit.ts, 54, 16)) +>foo : Symbol(foo, Decl(quantifiedTypesReduxToolkit.ts, 35, 17)) +>state.foo.slice : Symbol(String.slice, Decl(lib.es5.d.ts, --, --)) +>state.foo : Symbol(foo, Decl(quantifiedTypesReduxToolkit.ts, 35, 17)) +>state : Symbol(state, Decl(quantifiedTypesReduxToolkit.ts, 54, 16)) +>foo : Symbol(foo, Decl(quantifiedTypesReduxToolkit.ts, 35, 17)) +>slice : Symbol(String.slice, Decl(lib.es5.d.ts, --, --)) +>action.payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 52, 16)) +>action : Symbol(action, Decl(quantifiedTypesReduxToolkit.ts, 54, 22)) +>payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 52, 16)) + + }, + }, + invalidReducerWithPrepareNotation: { +>invalidReducerWithPrepareNotation : Symbol(invalidReducerWithPrepareNotation, Decl(quantifiedTypesReduxToolkit.ts, 57, 6)) + + prepare: (char: string, repeats: number) => { +>prepare : Symbol(prepare, Decl(quantifiedTypesReduxToolkit.ts, 58, 40)) +>char : Symbol(char, Decl(quantifiedTypesReduxToolkit.ts, 59, 16)) +>repeats : Symbol(repeats, Decl(quantifiedTypesReduxToolkit.ts, 59, 29)) + + return { payload: repeats * char.length } +>payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 60, 16)) +>repeats : Symbol(repeats, Decl(quantifiedTypesReduxToolkit.ts, 59, 29)) +>char.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) +>char : Symbol(char, Decl(quantifiedTypesReduxToolkit.ts, 59, 16)) +>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) + + }, + reducer: (state, action: PayloadAction) => { +>reducer : Symbol(reducer, Decl(quantifiedTypesReduxToolkit.ts, 61, 8)) +>state : Symbol(state, Decl(quantifiedTypesReduxToolkit.ts, 62, 16)) +>action : Symbol(action, Decl(quantifiedTypesReduxToolkit.ts, 62, 22)) +>PayloadAction : Symbol(PayloadAction, Decl(quantifiedTypesReduxToolkit.ts, 26, 3)) + + state.foo = action.payload +>state.foo : Symbol(foo, Decl(quantifiedTypesReduxToolkit.ts, 35, 17)) +>state : Symbol(state, Decl(quantifiedTypesReduxToolkit.ts, 62, 16)) +>foo : Symbol(foo, Decl(quantifiedTypesReduxToolkit.ts, 35, 17)) +>action.payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 30, 3)) +>action : Symbol(action, Decl(quantifiedTypesReduxToolkit.ts, 62, 22)) +>payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 30, 3)) + + }, + }, + } +}) + +{ + const _expectType: (payload: string) => PayloadAction = slice.actions.simpleReducer +>_expectType : Symbol(_expectType, Decl(quantifiedTypesReduxToolkit.ts, 70, 7)) +>payload : Symbol(payload, Decl(quantifiedTypesReduxToolkit.ts, 70, 22)) +>PayloadAction : Symbol(PayloadAction, Decl(quantifiedTypesReduxToolkit.ts, 26, 3)) +>slice.actions.simpleReducer : Symbol(simpleReducer, Decl(quantifiedTypesReduxToolkit.ts, 38, 13)) +>slice.actions : Symbol(actions, Decl(quantifiedTypesReduxToolkit.ts, 20, 3)) +>slice : Symbol(slice, Decl(quantifiedTypesReduxToolkit.ts, 33, 5)) +>actions : Symbol(actions, Decl(quantifiedTypesReduxToolkit.ts, 20, 3)) +>simpleReducer : Symbol(simpleReducer, Decl(quantifiedTypesReduxToolkit.ts, 38, 13)) +} +{ + const _expectType: (char: string, repeats: number) => PayloadAction = slice.actions.reducerWithPrepareNotation +>_expectType : Symbol(_expectType, Decl(quantifiedTypesReduxToolkit.ts, 73, 7)) +>char : Symbol(char, Decl(quantifiedTypesReduxToolkit.ts, 73, 22)) +>repeats : Symbol(repeats, Decl(quantifiedTypesReduxToolkit.ts, 73, 35)) +>PayloadAction : Symbol(PayloadAction, Decl(quantifiedTypesReduxToolkit.ts, 26, 3)) +>slice.actions.reducerWithPrepareNotation : Symbol(reducerWithPrepareNotation, Decl(quantifiedTypesReduxToolkit.ts, 41, 6)) +>slice.actions : Symbol(actions, Decl(quantifiedTypesReduxToolkit.ts, 20, 3)) +>slice : Symbol(slice, Decl(quantifiedTypesReduxToolkit.ts, 33, 5)) +>actions : Symbol(actions, Decl(quantifiedTypesReduxToolkit.ts, 20, 3)) +>reducerWithPrepareNotation : Symbol(reducerWithPrepareNotation, Decl(quantifiedTypesReduxToolkit.ts, 41, 6)) +} +{ + const _expectType: (char: string, repeats: number) => PayloadAction = slice.actions.reducerWithAnotherPrepareNotation +>_expectType : Symbol(_expectType, Decl(quantifiedTypesReduxToolkit.ts, 76, 7)) +>char : Symbol(char, Decl(quantifiedTypesReduxToolkit.ts, 76, 22)) +>repeats : Symbol(repeats, Decl(quantifiedTypesReduxToolkit.ts, 76, 35)) +>PayloadAction : Symbol(PayloadAction, Decl(quantifiedTypesReduxToolkit.ts, 26, 3)) +>slice.actions.reducerWithAnotherPrepareNotation : Symbol(reducerWithAnotherPrepareNotation, Decl(quantifiedTypesReduxToolkit.ts, 49, 6)) +>slice.actions : Symbol(actions, Decl(quantifiedTypesReduxToolkit.ts, 20, 3)) +>slice : Symbol(slice, Decl(quantifiedTypesReduxToolkit.ts, 33, 5)) +>actions : Symbol(actions, Decl(quantifiedTypesReduxToolkit.ts, 20, 3)) +>reducerWithAnotherPrepareNotation : Symbol(reducerWithAnotherPrepareNotation, Decl(quantifiedTypesReduxToolkit.ts, 49, 6)) +} + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.types b/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.types new file mode 100644 index 0000000000..357dd94445 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.types @@ -0,0 +1,273 @@ +//// [tests/cases/compiler/quantifiedTypesReduxToolkit.ts] //// + +=== quantifiedTypesReduxToolkit.ts === +// https://github.com/microsoft/TypeScript/issues/51612#issuecomment-1375431039 + +declare const createSlice: +>createSlice : { [T1 in T]:

Reducer; }>(slice: { name: string; initialState: S; reducers: Rs; }) => Slice + + < S extends object + , Rs extends { [T1 in T]:

Reducer } + > + (slice: { +>slice : { name: string; initialState: S; reducers: Rs; } + + name: string, +>name : string + + initialState: S, +>initialState : S + + reducers: Rs +>reducers : Rs + + }) => + Slice + +type Reducer = +>Reducer : Reducer + + | ((state: S, action: P & { type: T }) => void) +>state : S +>action : P & { type: T; } +>type : T + + | { reducer: (state: S, action: P & { type: T }) => void +>reducer : (state: S, action: P & { type: T; }) => void +>state : S +>action : P & { type: T; } +>type : T + + , prepare: (...a: never) => P +>prepare : (...a: never) => P +>a : never + } + +type Slice = +>Slice : Slice + + { actions: +>actions : { [K in keyof Rs]: Rs[K] extends { prepare: (...a: infer A) => infer R; } ? (...a: A) => { type: K; } & R : Rs[K] extends (state: never, action: PayloadAction) => unknown ? (payload: P) => { type: K; payload: P; } : never; } + + { [K in keyof Rs]: + Rs[K] extends { prepare: (...a: infer A) => infer R } ? (...a: A) => { type: K } & R : +>prepare : (...a: A) => R +>a : A +>a : A +>type : K + + Rs[K] extends (state: never, action: PayloadAction) => unknown ? (payload: P) => { type: K, payload: P } : +>state : never +>action : PayloadAction

+>payload : P +>type : K +>payload : P + + never + } + } + +type PayloadAction

= +>PayloadAction : PayloadAction

+ + { type: string +>type : string + + , payload: P +>payload : P + } + +const slice = createSlice({ +>slice : Slice<{ foo: string; }, { simpleReducer: (state: { foo: string; }, action: PayloadAction) => void; reducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { payload: string; extraStuff: boolean; }; reducer: (state: { foo: string; }, action: { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; }) => void; }; reducerWithAnotherPrepareNotation: { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; }) => void; }; invalidReducerWithPrepareNotation: any; }> +>createSlice({ name: "someSlice", initialState: { foo: "bar" }, reducers: { simpleReducer: (state, action: PayloadAction) => { state.foo = action.payload }, reducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { return { payload: char.repeat(repeats), extraStuff: true } }, reducer: (state, action) => { state.foo = action.payload } }, reducerWithAnotherPrepareNotation: { prepare: (char: string, repeats: number) => { return { payload: repeats * char.length } }, reducer: (state, action) => { state.foo = state.foo.slice(0, action.payload) }, }, invalidReducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { return { payload: repeats * char.length } }, reducer: (state, action: PayloadAction) => { state.foo = action.payload }, }, }}) : Slice<{ foo: string; }, { simpleReducer: (state: { foo: string; }, action: PayloadAction) => void; reducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { payload: string; extraStuff: boolean; }; reducer: (state: { foo: string; }, action: { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; }) => void; }; reducerWithAnotherPrepareNotation: { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; }) => void; }; invalidReducerWithPrepareNotation: any; }> +>createSlice : { [T1 in T]:

Reducer; }>(slice: { name: string; initialState: S; reducers: Rs; }) => Slice +>{ name: "someSlice", initialState: { foo: "bar" }, reducers: { simpleReducer: (state, action: PayloadAction) => { state.foo = action.payload }, reducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { return { payload: char.repeat(repeats), extraStuff: true } }, reducer: (state, action) => { state.foo = action.payload } }, reducerWithAnotherPrepareNotation: { prepare: (char: string, repeats: number) => { return { payload: repeats * char.length } }, reducer: (state, action) => { state.foo = state.foo.slice(0, action.payload) }, }, invalidReducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { return { payload: repeats * char.length } }, reducer: (state, action: PayloadAction) => { state.foo = action.payload }, }, }} : { name: string; initialState: { foo: string; }; reducers: { simpleReducer: (state: { foo: string; }, action: PayloadAction) => void; reducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { payload: string; extraStuff: boolean; }; reducer: (state: { foo: string; }, action: { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; }) => void; }; reducerWithAnotherPrepareNotation: { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; }) => void; }; invalidReducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: PayloadAction) => void; }; }; } + + name: "someSlice", +>name : string +>"someSlice" : "someSlice" + + initialState: { +>initialState : { foo: string; } +>{ foo: "bar" } : { foo: string; } + + foo: "bar" +>foo : string +>"bar" : "bar" + + }, + reducers: { +>reducers : { simpleReducer: (state: { foo: string; }, action: PayloadAction) => void; reducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { payload: string; extraStuff: boolean; }; reducer: (state: { foo: string; }, action: { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; }) => void; }; reducerWithAnotherPrepareNotation: { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; }) => void; }; invalidReducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: PayloadAction) => void; }; } +>{ simpleReducer: (state, action: PayloadAction) => { state.foo = action.payload }, reducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { return { payload: char.repeat(repeats), extraStuff: true } }, reducer: (state, action) => { state.foo = action.payload } }, reducerWithAnotherPrepareNotation: { prepare: (char: string, repeats: number) => { return { payload: repeats * char.length } }, reducer: (state, action) => { state.foo = state.foo.slice(0, action.payload) }, }, invalidReducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { return { payload: repeats * char.length } }, reducer: (state, action: PayloadAction) => { state.foo = action.payload }, }, } : { simpleReducer: (state: { foo: string; }, action: PayloadAction) => void; reducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { payload: string; extraStuff: boolean; }; reducer: (state: { foo: string; }, action: { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; }) => void; }; reducerWithAnotherPrepareNotation: { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; }) => void; }; invalidReducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: PayloadAction) => void; }; } + + simpleReducer: (state, action: PayloadAction) => { +>simpleReducer : (state: { foo: string; }, action: PayloadAction) => void +>(state, action: PayloadAction) => { state.foo = action.payload } : (state: { foo: string; }, action: PayloadAction) => void +>state : { foo: string; } +>action : PayloadAction + + state.foo = action.payload +>state.foo = action.payload : string +>state.foo : string +>state : { foo: string; } +>foo : string +>action.payload : string +>action : PayloadAction +>payload : string + + }, + reducerWithPrepareNotation: { +>reducerWithPrepareNotation : { prepare: (char: string, repeats: number) => { payload: string; extraStuff: boolean; }; reducer: (state: { foo: string; }, action: { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; }) => void; } +>{ prepare: (char: string, repeats: number) => { return { payload: char.repeat(repeats), extraStuff: true } }, reducer: (state, action) => { state.foo = action.payload } } : { prepare: (char: string, repeats: number) => { payload: string; extraStuff: boolean; }; reducer: (state: { foo: string; }, action: { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; }) => void; } + + prepare: (char: string, repeats: number) => { +>prepare : (char: string, repeats: number) => { payload: string; extraStuff: boolean; } +>(char: string, repeats: number) => { return { payload: char.repeat(repeats), extraStuff: true } } : (char: string, repeats: number) => { payload: string; extraStuff: boolean; } +>char : string +>repeats : number + + return { payload: char.repeat(repeats), extraStuff: true } +>{ payload: char.repeat(repeats), extraStuff: true } : { payload: string; extraStuff: true; } +>payload : string +>char.repeat(repeats) : string +>char.repeat : (count: number) => string +>char : string +>repeat : (count: number) => string +>repeats : number +>extraStuff : true +>true : true + + }, + reducer: (state, action) => { +>reducer : (state: { foo: string; }, action: { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; }) => void +>(state, action) => { state.foo = action.payload } : (state: { foo: string; }, action: { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; }) => void +>state : { foo: string; } +>action : { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; } + + state.foo = action.payload +>state.foo = action.payload : string +>state.foo : string +>state : { foo: string; } +>foo : string +>action.payload : string +>action : { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; } +>payload : string + } + }, + reducerWithAnotherPrepareNotation: { +>reducerWithAnotherPrepareNotation : { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; }) => void; } +>{ prepare: (char: string, repeats: number) => { return { payload: repeats * char.length } }, reducer: (state, action) => { state.foo = state.foo.slice(0, action.payload) }, } : { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; }) => void; } + + prepare: (char: string, repeats: number) => { +>prepare : (char: string, repeats: number) => { payload: number; } +>(char: string, repeats: number) => { return { payload: repeats * char.length } } : (char: string, repeats: number) => { payload: number; } +>char : string +>repeats : number + + return { payload: repeats * char.length } +>{ payload: repeats * char.length } : { payload: number; } +>payload : number +>repeats * char.length : number +>repeats : number +>char.length : number +>char : string +>length : number + + }, + reducer: (state, action) => { +>reducer : (state: { foo: string; }, action: { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; }) => void +>(state, action) => { state.foo = state.foo.slice(0, action.payload) } : (state: { foo: string; }, action: { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; }) => void +>state : { foo: string; } +>action : { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; } + + state.foo = state.foo.slice(0, action.payload) +>state.foo = state.foo.slice(0, action.payload) : string +>state.foo : string +>state : { foo: string; } +>foo : string +>state.foo.slice(0, action.payload) : string +>state.foo.slice : (start?: number, end?: number) => string +>state.foo : string +>state : { foo: string; } +>foo : string +>slice : (start?: number, end?: number) => string +>0 : 0 +>action.payload : number +>action : { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; } +>payload : number + + }, + }, + invalidReducerWithPrepareNotation: { +>invalidReducerWithPrepareNotation : { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: PayloadAction) => void; } +>{ prepare: (char: string, repeats: number) => { return { payload: repeats * char.length } }, reducer: (state, action: PayloadAction) => { state.foo = action.payload }, } : { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: PayloadAction) => void; } + + prepare: (char: string, repeats: number) => { +>prepare : (char: string, repeats: number) => { payload: number; } +>(char: string, repeats: number) => { return { payload: repeats * char.length } } : (char: string, repeats: number) => { payload: number; } +>char : string +>repeats : number + + return { payload: repeats * char.length } +>{ payload: repeats * char.length } : { payload: number; } +>payload : number +>repeats * char.length : number +>repeats : number +>char.length : number +>char : string +>length : number + + }, + reducer: (state, action: PayloadAction) => { +>reducer : (state: { foo: string; }, action: PayloadAction) => void +>(state, action: PayloadAction) => { state.foo = action.payload } : (state: { foo: string; }, action: PayloadAction) => void +>state : { foo: string; } +>action : PayloadAction + + state.foo = action.payload +>state.foo = action.payload : string +>state.foo : string +>state : { foo: string; } +>foo : string +>action.payload : string +>action : PayloadAction +>payload : string + + }, + }, + } +}) + +{ + const _expectType: (payload: string) => PayloadAction = slice.actions.simpleReducer +>_expectType : (payload: string) => PayloadAction +>payload : string +>slice.actions.simpleReducer : (payload: string) => { type: "simpleReducer"; payload: string; } +>slice.actions : { simpleReducer: (payload: string) => { type: "simpleReducer"; payload: string; }; reducerWithPrepareNotation: (char: string, repeats: number) => { type: "reducerWithPrepareNotation"; } & { payload: string; extraStuff: boolean; }; reducerWithAnotherPrepareNotation: (char: string, repeats: number) => { type: "reducerWithAnotherPrepareNotation"; } & { payload: number; }; invalidReducerWithPrepareNotation: any; } +>slice : Slice<{ foo: string; }, { simpleReducer: (state: { foo: string; }, action: PayloadAction) => void; reducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { payload: string; extraStuff: boolean; }; reducer: (state: { foo: string; }, action: { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; }) => void; }; reducerWithAnotherPrepareNotation: { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; }) => void; }; invalidReducerWithPrepareNotation: any; }> +>actions : { simpleReducer: (payload: string) => { type: "simpleReducer"; payload: string; }; reducerWithPrepareNotation: (char: string, repeats: number) => { type: "reducerWithPrepareNotation"; } & { payload: string; extraStuff: boolean; }; reducerWithAnotherPrepareNotation: (char: string, repeats: number) => { type: "reducerWithAnotherPrepareNotation"; } & { payload: number; }; invalidReducerWithPrepareNotation: any; } +>simpleReducer : (payload: string) => { type: "simpleReducer"; payload: string; } +} +{ + const _expectType: (char: string, repeats: number) => PayloadAction = slice.actions.reducerWithPrepareNotation +>_expectType : (char: string, repeats: number) => PayloadAction +>char : string +>repeats : number +>slice.actions.reducerWithPrepareNotation : (char: string, repeats: number) => { type: "reducerWithPrepareNotation"; } & { payload: string; extraStuff: boolean; } +>slice.actions : { simpleReducer: (payload: string) => { type: "simpleReducer"; payload: string; }; reducerWithPrepareNotation: (char: string, repeats: number) => { type: "reducerWithPrepareNotation"; } & { payload: string; extraStuff: boolean; }; reducerWithAnotherPrepareNotation: (char: string, repeats: number) => { type: "reducerWithAnotherPrepareNotation"; } & { payload: number; }; invalidReducerWithPrepareNotation: any; } +>slice : Slice<{ foo: string; }, { simpleReducer: (state: { foo: string; }, action: PayloadAction) => void; reducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { payload: string; extraStuff: boolean; }; reducer: (state: { foo: string; }, action: { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; }) => void; }; reducerWithAnotherPrepareNotation: { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; }) => void; }; invalidReducerWithPrepareNotation: any; }> +>actions : { simpleReducer: (payload: string) => { type: "simpleReducer"; payload: string; }; reducerWithPrepareNotation: (char: string, repeats: number) => { type: "reducerWithPrepareNotation"; } & { payload: string; extraStuff: boolean; }; reducerWithAnotherPrepareNotation: (char: string, repeats: number) => { type: "reducerWithAnotherPrepareNotation"; } & { payload: number; }; invalidReducerWithPrepareNotation: any; } +>reducerWithPrepareNotation : (char: string, repeats: number) => { type: "reducerWithPrepareNotation"; } & { payload: string; extraStuff: boolean; } +} +{ + const _expectType: (char: string, repeats: number) => PayloadAction = slice.actions.reducerWithAnotherPrepareNotation +>_expectType : (char: string, repeats: number) => PayloadAction +>char : string +>repeats : number +>slice.actions.reducerWithAnotherPrepareNotation : (char: string, repeats: number) => { type: "reducerWithAnotherPrepareNotation"; } & { payload: number; } +>slice.actions : { simpleReducer: (payload: string) => { type: "simpleReducer"; payload: string; }; reducerWithPrepareNotation: (char: string, repeats: number) => { type: "reducerWithPrepareNotation"; } & { payload: string; extraStuff: boolean; }; reducerWithAnotherPrepareNotation: (char: string, repeats: number) => { type: "reducerWithAnotherPrepareNotation"; } & { payload: number; }; invalidReducerWithPrepareNotation: any; } +>slice : Slice<{ foo: string; }, { simpleReducer: (state: { foo: string; }, action: PayloadAction) => void; reducerWithPrepareNotation: { prepare: (char: string, repeats: number) => { payload: string; extraStuff: boolean; }; reducer: (state: { foo: string; }, action: { payload: string; extraStuff: boolean; } & { type: "reducerWithPrepareNotation"; }) => void; }; reducerWithAnotherPrepareNotation: { prepare: (char: string, repeats: number) => { payload: number; }; reducer: (state: { foo: string; }, action: { payload: number; } & { type: "reducerWithAnotherPrepareNotation"; }) => void; }; invalidReducerWithPrepareNotation: any; }> +>actions : { simpleReducer: (payload: string) => { type: "simpleReducer"; payload: string; }; reducerWithPrepareNotation: (char: string, repeats: number) => { type: "reducerWithPrepareNotation"; } & { payload: string; extraStuff: boolean; }; reducerWithAnotherPrepareNotation: (char: string, repeats: number) => { type: "reducerWithAnotherPrepareNotation"; } & { payload: number; }; invalidReducerWithPrepareNotation: any; } +>reducerWithAnotherPrepareNotation : (char: string, repeats: number) => { type: "reducerWithAnotherPrepareNotation"; } & { payload: number; } +} + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesCaseInsensitve.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesCaseInsensitve.errors.txt new file mode 100644 index 0000000000..7eb9c7328a --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesCaseInsensitve.errors.txt @@ -0,0 +1,22 @@ +quantifiedTypesSelfTypesCaseInsensitve.ts(16,11): error TS2322: Type '"Acept"' is not assignable to type '"Error: Type 'Acept' is not assignable to type 'CaseInsensitive'" | "Error: Type 'Acept' is not assignable to type 'CaseInsensitive'"'. + + +==== quantifiedTypesSelfTypesCaseInsensitve.ts (1 errors) ==== + type PasreCaseInsensitive = + Self extends string + ? Lowercase extends Lowercase + ? Self + : `Error: Type '${Self}' is not assignable to type 'CaseInsensitive<${T}>'` + : T + + type CaseInsensitive = PasreCaseInsensitive + + declare const setHeader: + (key: CaseInsensitive<"Set-Cookie" | "Accept">, value: string) => void + + setHeader("Set-Cookie", "test") + setHeader("Accept", "test2") + setHeader("sEt-cOoKiE", "stop writing headers like this but ok") + setHeader("Acept", "nah this has a typo") + ~~~~~~~ +!!! error TS2322: Type '"Acept"' is not assignable to type '"Error: Type 'Acept' is not assignable to type 'CaseInsensitive'" | "Error: Type 'Acept' is not assignable to type 'CaseInsensitive'"'. \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesCaseInsensitve.js b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesCaseInsensitve.js new file mode 100644 index 0000000000..6175a59ba0 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesCaseInsensitve.js @@ -0,0 +1,25 @@ +//// [tests/cases/compiler/quantifiedTypesSelfTypesCaseInsensitve.ts] //// + +//// [quantifiedTypesSelfTypesCaseInsensitve.ts] +type PasreCaseInsensitive = + Self extends string + ? Lowercase extends Lowercase + ? Self + : `Error: Type '${Self}' is not assignable to type 'CaseInsensitive<${T}>'` + : T + +type CaseInsensitive = PasreCaseInsensitive + +declare const setHeader: + (key: CaseInsensitive<"Set-Cookie" | "Accept">, value: string) => void + +setHeader("Set-Cookie", "test") +setHeader("Accept", "test2") +setHeader("sEt-cOoKiE", "stop writing headers like this but ok") +setHeader("Acept", "nah this has a typo") + +//// [quantifiedTypesSelfTypesCaseInsensitve.js] +setHeader("Set-Cookie", "test"); +setHeader("Accept", "test2"); +setHeader("sEt-cOoKiE", "stop writing headers like this but ok"); +setHeader("Acept", "nah this has a typo"); diff --git a/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesCaseInsensitve.symbols b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesCaseInsensitve.symbols new file mode 100644 index 0000000000..0ce23b0287 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesCaseInsensitve.symbols @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/quantifiedTypesSelfTypesCaseInsensitve.ts] //// + +=== quantifiedTypesSelfTypesCaseInsensitve.ts === +type PasreCaseInsensitive = +>PasreCaseInsensitive : Symbol(PasreCaseInsensitive, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 0, 0)) +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 0, 26)) +>T : Symbol(T, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 0, 31)) + + Self extends string +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 0, 26)) + + ? Lowercase extends Lowercase +>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --)) +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 0, 26)) +>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 0, 31)) + + ? Self +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 0, 26)) + + : `Error: Type '${Self}' is not assignable to type 'CaseInsensitive<${T}>'` +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 0, 26)) +>T : Symbol(T, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 0, 31)) + + : T +>T : Symbol(T, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 0, 31)) + +type CaseInsensitive = PasreCaseInsensitive +>CaseInsensitive : Symbol(CaseInsensitive, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 5, 7)) +>T : Symbol(T, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 7, 21)) +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 7, 42)) +>PasreCaseInsensitive : Symbol(PasreCaseInsensitive, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 0, 0)) +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 7, 42)) +>T : Symbol(T, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 7, 21)) + +declare const setHeader: +>setHeader : Symbol(setHeader, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 9, 13)) + + (key: CaseInsensitive<"Set-Cookie" | "Accept">, value: string) => void +>key : Symbol(key, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 10, 3)) +>CaseInsensitive : Symbol(CaseInsensitive, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 5, 7)) +>value : Symbol(value, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 10, 49)) + +setHeader("Set-Cookie", "test") +>setHeader : Symbol(setHeader, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 9, 13)) + +setHeader("Accept", "test2") +>setHeader : Symbol(setHeader, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 9, 13)) + +setHeader("sEt-cOoKiE", "stop writing headers like this but ok") +>setHeader : Symbol(setHeader, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 9, 13)) + +setHeader("Acept", "nah this has a typo") +>setHeader : Symbol(setHeader, Decl(quantifiedTypesSelfTypesCaseInsensitve.ts, 9, 13)) + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesCaseInsensitve.types b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesCaseInsensitve.types new file mode 100644 index 0000000000..81fd7caee9 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesCaseInsensitve.types @@ -0,0 +1,46 @@ +//// [tests/cases/compiler/quantifiedTypesSelfTypesCaseInsensitve.ts] //// + +=== quantifiedTypesSelfTypesCaseInsensitve.ts === +type PasreCaseInsensitive = +>PasreCaseInsensitive : PasreCaseInsensitive + + Self extends string + ? Lowercase extends Lowercase + ? Self + : `Error: Type '${Self}' is not assignable to type 'CaseInsensitive<${T}>'` + : T + +type CaseInsensitive = PasreCaseInsensitive +>CaseInsensitive : PasreCaseInsensitive + +declare const setHeader: +>setHeader : (key: PasreCaseInsensitive, value: string) => void + + (key: CaseInsensitive<"Set-Cookie" | "Accept">, value: string) => void +>key : PasreCaseInsensitive +>value : string + +setHeader("Set-Cookie", "test") +>setHeader("Set-Cookie", "test") : void +>setHeader : (key: PasreCaseInsensitive, value: string) => void +>"Set-Cookie" : "Set-Cookie" +>"test" : "test" + +setHeader("Accept", "test2") +>setHeader("Accept", "test2") : void +>setHeader : (key: PasreCaseInsensitive, value: string) => void +>"Accept" : "Accept" +>"test2" : "test2" + +setHeader("sEt-cOoKiE", "stop writing headers like this but ok") +>setHeader("sEt-cOoKiE", "stop writing headers like this but ok") : void +>setHeader : (key: PasreCaseInsensitive, value: string) => void +>"sEt-cOoKiE" : "sEt-cOoKiE" +>"stop writing headers like this but ok" : "stop writing headers like this but ok" + +setHeader("Acept", "nah this has a typo") +>setHeader("Acept", "nah this has a typo") : void +>setHeader : (key: PasreCaseInsensitive, value: string) => void +>"Acept" : any +>"nah this has a typo" : "nah this has a typo" + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesStateMachine.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesStateMachine.errors.txt new file mode 100644 index 0000000000..6332d61108 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesStateMachine.errors.txt @@ -0,0 +1,45 @@ +quantifiedTypesSelfTypesStateMachine.ts(35,5): error TS2820: Type '"reddd"' is not assignable to type '"green" | "off" | "red" | "yellow"'. Did you mean '"red"'? + + +==== quantifiedTypesSelfTypesStateMachine.ts (1 errors) ==== + type ParseStateMachine = { [S in keyof Self]: { [E in keyof Self[S]]: keyof Self } } + type StateMachine = > Self + + let trafficLights: StateMachine = { + off: { + ON: "red" + }, + red: { + TICK: "yellow", + OFF: "off" + }, + yellow: { + TICK: "green", + OFF: "off" + }, + green: { + TICK: "red", + OFF: "off" + } + } + + let trafficLightsInvalid: StateMachine = { + off: { + ON: "red" + }, + red: { + TICK: "yellow", + OFF: "off" + }, + yellow: { + TICK: "green", + OFF: "off" + }, + green: { + TICK: "reddd", + ~~~~ +!!! error TS2820: Type '"reddd"' is not assignable to type '"green" | "off" | "red" | "yellow"'. Did you mean '"red"'? +!!! related TS6500 quantifiedTypesSelfTypesStateMachine.ts:35:5: The expected type comes from property 'TICK' which is declared here on type '{ TICK: "green" | "off" | "red" | "yellow"; OFF: "green" | "off" | "red" | "yellow"; }' + OFF: "off" + } + } \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesStateMachine.js b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesStateMachine.js new file mode 100644 index 0000000000..ac06e2aedb --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesStateMachine.js @@ -0,0 +1,77 @@ +//// [tests/cases/compiler/quantifiedTypesSelfTypesStateMachine.ts] //// + +//// [quantifiedTypesSelfTypesStateMachine.ts] +type ParseStateMachine = { [S in keyof Self]: { [E in keyof Self[S]]: keyof Self } } +type StateMachine = > Self + +let trafficLights: StateMachine = { + off: { + ON: "red" + }, + red: { + TICK: "yellow", + OFF: "off" + }, + yellow: { + TICK: "green", + OFF: "off" + }, + green: { + TICK: "red", + OFF: "off" + } +} + +let trafficLightsInvalid: StateMachine = { + off: { + ON: "red" + }, + red: { + TICK: "yellow", + OFF: "off" + }, + yellow: { + TICK: "green", + OFF: "off" + }, + green: { + TICK: "reddd", + OFF: "off" + } +} + +//// [quantifiedTypesSelfTypesStateMachine.js] +let trafficLights = { + off: { + ON: "red" + }, + red: { + TICK: "yellow", + OFF: "off" + }, + yellow: { + TICK: "green", + OFF: "off" + }, + green: { + TICK: "red", + OFF: "off" + } +}; +let trafficLightsInvalid = { + off: { + ON: "red" + }, + red: { + TICK: "yellow", + OFF: "off" + }, + yellow: { + TICK: "green", + OFF: "off" + }, + green: { + TICK: "reddd", + OFF: "off" + } +}; diff --git a/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesStateMachine.symbols b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesStateMachine.symbols new file mode 100644 index 0000000000..3c5167ee4d --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesStateMachine.symbols @@ -0,0 +1,103 @@ +//// [tests/cases/compiler/quantifiedTypesSelfTypesStateMachine.ts] //// + +=== quantifiedTypesSelfTypesStateMachine.ts === +type ParseStateMachine = { [S in keyof Self]: { [E in keyof Self[S]]: keyof Self } } +>ParseStateMachine : Symbol(ParseStateMachine, Decl(quantifiedTypesSelfTypesStateMachine.ts, 0, 0)) +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesStateMachine.ts, 0, 23)) +>S : Symbol(S, Decl(quantifiedTypesSelfTypesStateMachine.ts, 0, 34)) +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesStateMachine.ts, 0, 23)) +>E : Symbol(E, Decl(quantifiedTypesSelfTypesStateMachine.ts, 0, 55)) +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesStateMachine.ts, 0, 23)) +>S : Symbol(S, Decl(quantifiedTypesSelfTypesStateMachine.ts, 0, 34)) +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesStateMachine.ts, 0, 23)) + +type StateMachine = > Self +>StateMachine : Symbol(StateMachine, Decl(quantifiedTypesSelfTypesStateMachine.ts, 0, 90)) +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesStateMachine.ts, 1, 21)) +>ParseStateMachine : Symbol(ParseStateMachine, Decl(quantifiedTypesSelfTypesStateMachine.ts, 0, 0)) +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesStateMachine.ts, 1, 21)) +>Self : Symbol(Self, Decl(quantifiedTypesSelfTypesStateMachine.ts, 1, 21)) + +let trafficLights: StateMachine = { +>trafficLights : Symbol(trafficLights, Decl(quantifiedTypesSelfTypesStateMachine.ts, 3, 3)) +>StateMachine : Symbol(StateMachine, Decl(quantifiedTypesSelfTypesStateMachine.ts, 0, 90)) + + off: { +>off : Symbol(off, Decl(quantifiedTypesSelfTypesStateMachine.ts, 3, 35)) + + ON: "red" +>ON : Symbol(ON, Decl(quantifiedTypesSelfTypesStateMachine.ts, 4, 8)) + + }, + red: { +>red : Symbol(red, Decl(quantifiedTypesSelfTypesStateMachine.ts, 6, 4)) + + TICK: "yellow", +>TICK : Symbol(TICK, Decl(quantifiedTypesSelfTypesStateMachine.ts, 7, 8)) + + OFF: "off" +>OFF : Symbol(OFF, Decl(quantifiedTypesSelfTypesStateMachine.ts, 8, 19)) + + }, + yellow: { +>yellow : Symbol(yellow, Decl(quantifiedTypesSelfTypesStateMachine.ts, 10, 4)) + + TICK: "green", +>TICK : Symbol(TICK, Decl(quantifiedTypesSelfTypesStateMachine.ts, 11, 11)) + + OFF: "off" +>OFF : Symbol(OFF, Decl(quantifiedTypesSelfTypesStateMachine.ts, 12, 18)) + + }, + green: { +>green : Symbol(green, Decl(quantifiedTypesSelfTypesStateMachine.ts, 14, 4)) + + TICK: "red", +>TICK : Symbol(TICK, Decl(quantifiedTypesSelfTypesStateMachine.ts, 15, 10)) + + OFF: "off" +>OFF : Symbol(OFF, Decl(quantifiedTypesSelfTypesStateMachine.ts, 16, 16)) + } +} + +let trafficLightsInvalid: StateMachine = { +>trafficLightsInvalid : Symbol(trafficLightsInvalid, Decl(quantifiedTypesSelfTypesStateMachine.ts, 21, 3)) +>StateMachine : Symbol(StateMachine, Decl(quantifiedTypesSelfTypesStateMachine.ts, 0, 90)) + + off: { +>off : Symbol(off, Decl(quantifiedTypesSelfTypesStateMachine.ts, 21, 42)) + + ON: "red" +>ON : Symbol(ON, Decl(quantifiedTypesSelfTypesStateMachine.ts, 22, 8)) + + }, + red: { +>red : Symbol(red, Decl(quantifiedTypesSelfTypesStateMachine.ts, 24, 4)) + + TICK: "yellow", +>TICK : Symbol(TICK, Decl(quantifiedTypesSelfTypesStateMachine.ts, 25, 8)) + + OFF: "off" +>OFF : Symbol(OFF, Decl(quantifiedTypesSelfTypesStateMachine.ts, 26, 19)) + + }, + yellow: { +>yellow : Symbol(yellow, Decl(quantifiedTypesSelfTypesStateMachine.ts, 28, 4)) + + TICK: "green", +>TICK : Symbol(TICK, Decl(quantifiedTypesSelfTypesStateMachine.ts, 29, 11)) + + OFF: "off" +>OFF : Symbol(OFF, Decl(quantifiedTypesSelfTypesStateMachine.ts, 30, 18)) + + }, + green: { +>green : Symbol(green, Decl(quantifiedTypesSelfTypesStateMachine.ts, 32, 4)) + + TICK: "reddd", +>TICK : Symbol(TICK, Decl(quantifiedTypesSelfTypesStateMachine.ts, 33, 10)) + + OFF: "off" +>OFF : Symbol(OFF, Decl(quantifiedTypesSelfTypesStateMachine.ts, 34, 18)) + } +} diff --git a/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesStateMachine.types b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesStateMachine.types new file mode 100644 index 0000000000..59bd1d8cb9 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesSelfTypesStateMachine.types @@ -0,0 +1,114 @@ +//// [tests/cases/compiler/quantifiedTypesSelfTypesStateMachine.ts] //// + +=== quantifiedTypesSelfTypesStateMachine.ts === +type ParseStateMachine = { [S in keyof Self]: { [E in keyof Self[S]]: keyof Self } } +>ParseStateMachine : ParseStateMachine + +type StateMachine = > Self +>StateMachine : > Self + +let trafficLights: StateMachine = { +>trafficLights : > Self +>{ off: { ON: "red" }, red: { TICK: "yellow", OFF: "off" }, yellow: { TICK: "green", OFF: "off" }, green: { TICK: "red", OFF: "off" }} : { off: { ON: "red"; }; red: { TICK: "yellow"; OFF: "off"; }; yellow: { TICK: "green"; OFF: "off"; }; green: { TICK: "red"; OFF: "off"; }; } + + off: { +>off : { ON: string; } +>{ ON: "red" } : { ON: string; } + + ON: "red" +>ON : string +>"red" : "red" + + }, + red: { +>red : { TICK: string; OFF: string; } +>{ TICK: "yellow", OFF: "off" } : { TICK: string; OFF: string; } + + TICK: "yellow", +>TICK : string +>"yellow" : "yellow" + + OFF: "off" +>OFF : string +>"off" : "off" + + }, + yellow: { +>yellow : { TICK: string; OFF: string; } +>{ TICK: "green", OFF: "off" } : { TICK: string; OFF: string; } + + TICK: "green", +>TICK : string +>"green" : "green" + + OFF: "off" +>OFF : string +>"off" : "off" + + }, + green: { +>green : { TICK: string; OFF: string; } +>{ TICK: "red", OFF: "off" } : { TICK: string; OFF: string; } + + TICK: "red", +>TICK : string +>"red" : "red" + + OFF: "off" +>OFF : string +>"off" : "off" + } +} + +let trafficLightsInvalid: StateMachine = { +>trafficLightsInvalid : > Self +>{ off: { ON: "red" }, red: { TICK: "yellow", OFF: "off" }, yellow: { TICK: "green", OFF: "off" }, green: { TICK: "reddd", OFF: "off" }} : any + + off: { +>off : { ON: string; } +>{ ON: "red" } : { ON: string; } + + ON: "red" +>ON : string +>"red" : "red" + + }, + red: { +>red : { TICK: string; OFF: string; } +>{ TICK: "yellow", OFF: "off" } : { TICK: string; OFF: string; } + + TICK: "yellow", +>TICK : string +>"yellow" : "yellow" + + OFF: "off" +>OFF : string +>"off" : "off" + + }, + yellow: { +>yellow : { TICK: string; OFF: string; } +>{ TICK: "green", OFF: "off" } : { TICK: string; OFF: string; } + + TICK: "green", +>TICK : string +>"green" : "green" + + OFF: "off" +>OFF : string +>"off" : "off" + + }, + green: { +>green : { TICK: string; OFF: string; } +>{ TICK: "reddd", OFF: "off" } : { TICK: string; OFF: string; } + + TICK: "reddd", +>TICK : string +>"reddd" : "reddd" + + OFF: "off" +>OFF : string +>"off" : "off" + } +} diff --git a/testdata/tests/cases/compiler/allowQuantifiedTypes.ts b/testdata/tests/cases/compiler/allowQuantifiedTypes.ts new file mode 100644 index 0000000000..2c1b5080f6 --- /dev/null +++ b/testdata/tests/cases/compiler/allowQuantifiedTypes.ts @@ -0,0 +1,3 @@ +type T0 = { values: T[], identifier: (value: T) => string } +type T1 = (t: T) => T +type T2 = (u: U) => U \ No newline at end of file diff --git a/testdata/tests/cases/compiler/quantifiedTypesAdvanced.ts b/testdata/tests/cases/compiler/quantifiedTypesAdvanced.ts new file mode 100644 index 0000000000..d3ecd39e6d --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesAdvanced.ts @@ -0,0 +1,38 @@ +declare const f: + { a: A, ab: (a: A) => B, bc?: (b: B) => C })[]>(a: [...T]) => + { [K in keyof T]: T[K] extends { bc: (...a: never) => infer C } ? C : "lol" } + +let t0 = f([ + { + a: "0", + ab: a => +a, + bc: b => typeof b === "number" + }, + { + a: "hello", + ab: a => a + " world", + bc: b => { + b satisfies string + return +b + } + }, + { + a: 42, + ab: a => a.toString() + } +]) + + +let t1 = f([ + { + a: true, + ab: a => +a, + bc: b => typeof b === "number" + }, + { + a: "hello", + ab: a => a + " world", + bc: b => +b, + extra: "foo" // TODO: an extra property should be allowed + } +]) \ No newline at end of file diff --git a/testdata/tests/cases/compiler/quantifiedTypesBasic.ts b/testdata/tests/cases/compiler/quantifiedTypesBasic.ts new file mode 100644 index 0000000000..7abdd40a2a --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesBasic.ts @@ -0,0 +1,11 @@ +let t0: T = "hello" + +let t1: { values: T[], identifier: (value: T) => string } = { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key +} + +let t2: { values: T[], identifier: (value: T) => string } = { + values: [{ key: "a" }, { key: "b" }, { key: 0 }], + identifier: v => v.key +} diff --git a/testdata/tests/cases/compiler/quantifiedTypesBasic2.ts b/testdata/tests/cases/compiler/quantifiedTypesBasic2.ts new file mode 100644 index 0000000000..adb6a4cfdc --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesBasic2.ts @@ -0,0 +1,12 @@ +declare const f1: (t: T) => void +f1("hello") + +declare const f2: (t: { values: T[], identifier: (value: T) => string }) => void +f2({ + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key +}) +f2({ + values: [{ key: "a" }, { key: "b" }, { key: 0 }], + identifier: v => v.key +}) diff --git a/testdata/tests/cases/compiler/quantifiedTypesConstraints.ts b/testdata/tests/cases/compiler/quantifiedTypesConstraints.ts new file mode 100644 index 0000000000..e32b1c9dda --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesConstraints.ts @@ -0,0 +1,7 @@ +type Input = { values: T[], identifier: (value: T) => string } +declare const f: (t: Input) => void + +f({ + values: ["a", "b", "c"], + identifier: v => v +}) \ No newline at end of file diff --git a/testdata/tests/cases/compiler/quantifiedTypesIntermediate.ts b/testdata/tests/cases/compiler/quantifiedTypesIntermediate.ts new file mode 100644 index 0000000000..b1f0876e06 --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesIntermediate.ts @@ -0,0 +1,40 @@ +type Input = { values: T[], identifier: (value: T) => string } +declare const f: (t: ( Input)[]) => void + +f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + } +]) + +f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => Number(v.key) + } +]) + + +f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + }, + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => Number(v.key) + } +]) + + +f([ + { + values: [{ key: "a" }, { key: "b" }, { key: "c" }], + identifier: v => v.key + }, + { + values: [{ id: 1 }, { id: 2 }, { id: 3 }], + identifier: v => v.id.toString() + } +]) diff --git a/testdata/tests/cases/compiler/quantifiedTypesNormalizedShapes.ts b/testdata/tests/cases/compiler/quantifiedTypesNormalizedShapes.ts new file mode 100644 index 0000000000..5a06230a30 --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesNormalizedShapes.ts @@ -0,0 +1,18 @@ +type NormalizedRecord = + { [K in Id]: Omit & { id: K } } + +interface Layer { + id: string + color: string +} + +let layers: NormalizedRecord = { + a: { + id: "a", + color: "green" + }, + b: { + id: "a", // should have been "b" + color: "blue" + } +} diff --git a/testdata/tests/cases/compiler/quantifiedTypesParentInferenceContext.ts b/testdata/tests/cases/compiler/quantifiedTypesParentInferenceContext.ts new file mode 100644 index 0000000000..3fba34c1f1 --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesParentInferenceContext.ts @@ -0,0 +1,2 @@ +declare const f: (a: A, f: [(a: A) => void]) => void +f(0, [a => {}]) diff --git a/testdata/tests/cases/compiler/quantifiedTypesParentInferenceContext2.ts b/testdata/tests/cases/compiler/quantifiedTypesParentInferenceContext2.ts new file mode 100644 index 0000000000..ec538b5d50 --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesParentInferenceContext2.ts @@ -0,0 +1,2 @@ +declare const f: (a: A, f: [ ((a: A) => void)]) => void +f(0, [a => {}]) \ No newline at end of file diff --git a/testdata/tests/cases/compiler/quantifiedTypesParentInferenceContext3.ts b/testdata/tests/cases/compiler/quantifiedTypesParentInferenceContext3.ts new file mode 100644 index 0000000000..168335e035 --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesParentInferenceContext3.ts @@ -0,0 +1,2 @@ +declare const f: (x: { a: A, f: [ ((a: A) => void)] }) => void +f({ a: 0, f: [a => { a satisfies number; }] }) diff --git a/testdata/tests/cases/compiler/quantifiedTypesReduxToolkit.ts b/testdata/tests/cases/compiler/quantifiedTypesReduxToolkit.ts new file mode 100644 index 0000000000..522a3f52c7 --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesReduxToolkit.ts @@ -0,0 +1,79 @@ +// @lib: esnext +// https://github.com/microsoft/TypeScript/issues/51612#issuecomment-1375431039 + +declare const createSlice: + < S extends object + , Rs extends { [T1 in T]:

Reducer } + > + (slice: { + name: string, + initialState: S, + reducers: Rs + }) => + Slice + +type Reducer = + | ((state: S, action: P & { type: T }) => void) + | { reducer: (state: S, action: P & { type: T }) => void + , prepare: (...a: never) => P + } + +type Slice = + { actions: + { [K in keyof Rs]: + Rs[K] extends { prepare: (...a: infer A) => infer R } ? (...a: A) => { type: K } & R : + Rs[K] extends (state: never, action: PayloadAction) => unknown ? (payload: P) => { type: K, payload: P } : + never + } + } + +type PayloadAction

= + { type: string + , payload: P + } + +const slice = createSlice({ + name: "someSlice", + initialState: { + foo: "bar" + }, + reducers: { + simpleReducer: (state, action: PayloadAction) => { + state.foo = action.payload + }, + reducerWithPrepareNotation: { + prepare: (char: string, repeats: number) => { + return { payload: char.repeat(repeats), extraStuff: true } + }, + reducer: (state, action) => { + state.foo = action.payload + } + }, + reducerWithAnotherPrepareNotation: { + prepare: (char: string, repeats: number) => { + return { payload: repeats * char.length } + }, + reducer: (state, action) => { + state.foo = state.foo.slice(0, action.payload) + }, + }, + invalidReducerWithPrepareNotation: { + prepare: (char: string, repeats: number) => { + return { payload: repeats * char.length } + }, + reducer: (state, action: PayloadAction) => { + state.foo = action.payload + }, + }, + } +}) + +{ + const _expectType: (payload: string) => PayloadAction = slice.actions.simpleReducer +} +{ + const _expectType: (char: string, repeats: number) => PayloadAction = slice.actions.reducerWithPrepareNotation +} +{ + const _expectType: (char: string, repeats: number) => PayloadAction = slice.actions.reducerWithAnotherPrepareNotation +} diff --git a/testdata/tests/cases/compiler/quantifiedTypesSelfTypesCaseInsensitve.ts b/testdata/tests/cases/compiler/quantifiedTypesSelfTypesCaseInsensitve.ts new file mode 100644 index 0000000000..324a8920bb --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesSelfTypesCaseInsensitve.ts @@ -0,0 +1,16 @@ +type PasreCaseInsensitive = + Self extends string + ? Lowercase extends Lowercase + ? Self + : `Error: Type '${Self}' is not assignable to type 'CaseInsensitive<${T}>'` + : T + +type CaseInsensitive = PasreCaseInsensitive + +declare const setHeader: + (key: CaseInsensitive<"Set-Cookie" | "Accept">, value: string) => void + +setHeader("Set-Cookie", "test") +setHeader("Accept", "test2") +setHeader("sEt-cOoKiE", "stop writing headers like this but ok") +setHeader("Acept", "nah this has a typo") \ No newline at end of file diff --git a/testdata/tests/cases/compiler/quantifiedTypesSelfTypesStateMachine.ts b/testdata/tests/cases/compiler/quantifiedTypesSelfTypesStateMachine.ts new file mode 100644 index 0000000000..bd9746035b --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesSelfTypesStateMachine.ts @@ -0,0 +1,38 @@ +type ParseStateMachine = { [S in keyof Self]: { [E in keyof Self[S]]: keyof Self } } +type StateMachine = > Self + +let trafficLights: StateMachine = { + off: { + ON: "red" + }, + red: { + TICK: "yellow", + OFF: "off" + }, + yellow: { + TICK: "green", + OFF: "off" + }, + green: { + TICK: "red", + OFF: "off" + } +} + +let trafficLightsInvalid: StateMachine = { + off: { + ON: "red" + }, + red: { + TICK: "yellow", + OFF: "off" + }, + yellow: { + TICK: "green", + OFF: "off" + }, + green: { + TICK: "reddd", + OFF: "off" + } +} \ No newline at end of file