diff --git a/internal/ast/ast.go b/internal/ast/ast.go index 3d6dbcffcc6..acd5d37875b 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 ed98bd68ff6..6a359cefedc 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 3430cc2cb10..4a6ac4ed3a4 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 9acf84a78f4..b3113f62ef2 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 f7339d98702..341beb946b7 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 f2a212a0609..956bf91e07a 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,64 @@ 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 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 t.flags&TypeFlagsUnion != 0 { + return t // if it's a union then the subtype relation checking is non-trivial and we'll let the relater handle it + } + + 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 @@ -8318,6 +8380,9 @@ func (c *Checker) resolveCallExpression(node *ast.Node, candidatesOutArray *[]*S } var callChainFlags SignatureFlags funcType := c.checkExpression(node.Expression()) + if funcType.flags&TypeFlagsQuantified != 0 { + funcType = funcType.AsQuantifiedType().baseType + } if isCallChain(node) { nonOptionalType := c.getOptionalExpressionType(funcType, node.Expression()) switch { @@ -9937,12 +10002,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 { @@ -10918,6 +10983,9 @@ func (c *Checker) checkPropertyAccessChain(node *ast.Node, checkMode CheckMode) } func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, left *ast.Node, leftType *Type, right *ast.Node, checkMode CheckMode, writeOnly bool) *Type { + if leftType.flags&TypeFlagsQuantified != 0 { + return c.checkPropertyAccessExpressionOrQualifiedName(node, left, leftType.AsQuantifiedType().baseType, right, checkMode, writeOnly) + } parentSymbol := c.getResolvedSymbolOrNil(left) assignmentKind := getAssignmentTargetKind(node) widenedType := leftType @@ -16054,6 +16122,23 @@ func (c *Checker) getTypeOfVariableOrParameterOrProperty(symbol *ast.Symbol) *Ty if t == nil { panic("Unexpected nil type") } + if t.objectFlags&ObjectFlagsContainsQuantifiedType != 0 { + mapper := make(map[*Type]*Type) + t = c.instantiateType(t, newFunctionTypeMapper(func(t *Type) *Type { + if t.objectFlags&ObjectFlagsQuantifiedTypeParameter != 0 { + newT, seen := mapper[t] + if seen { + return newT + } + newT = c.cloneTypeParameter(t) + newT.objectFlags |= ObjectFlagsQuantifiedTypeParameter + newT.AsTypeParameter().boundedTo = symbol + mapper[t] = newT + return newT + } + return t + })) + } // For a contextually typed parameter it is possible that a type has already // been assigned (in assignTypeToParameterAndFixTypeParameters), and we want // to preserve this type. In fact, we need to _prefer_ that type, but it won't @@ -16821,7 +16906,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 @@ -17216,6 +17301,9 @@ func (c *Checker) getBindingElementTypeFromParentType(declaration *ast.Node, par } else if c.strictNullChecks && pattern.Parent.Initializer() != nil && !(c.hasTypeFacts(c.getTypeOfInitializer(pattern.Parent.Initializer()), TypeFactsEQUndefined)) { parentType = c.getTypeWithFacts(parentType, TypeFactsNEUndefined) } + if parentType.flags&TypeFlagsQuantified != 0 { + parentType = parentType.AsQuantifiedType().baseType + } accessFlags := AccessFlagsExpressionPosition | core.IfElse(noTupleBoundsCheck || c.hasDefaultValue(declaration), AccessFlagsAllowMissing, 0) var t *Type switch pattern.Kind { @@ -20877,7 +20965,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) @@ -21605,7 +21693,25 @@ func (c *Checker) instantiateTypeWorker(t *Type, m *TypeMapper, alias *TypeAlias flags := t.flags switch { case flags&TypeFlagsTypeParameter != 0: - return m.Map(t) + newT := m.Map(t) + if newT.objectFlags&ObjectFlagsQuantifiedTypeParameter != 0 { + newT.AsTypeParameter().mapper = c.combineTypeMappers(newT.AsTypeParameter().mapper, m) + } + return newT + case flags&TypeFlagsQuantified != 0: + return c.newQuantifiedType( + core.Map( + c.instantiateTypes( + core.Map( + t.AsQuantifiedType().typeParameters, + func(tp *TypeParameter) *Type { return tp.AsType() }, + ), + m, + ), + func(t *Type) *TypeParameter { return t.AsTypeParameter() }, + ), + c.instantiateType(t.AsQuantifiedType().baseType, m), + ) case flags&TypeFlagsObject != 0: objectFlags := t.objectFlags if objectFlags&(ObjectFlagsReference|ObjectFlagsAnonymous|ObjectFlagsMapped) != 0 { @@ -22277,6 +22383,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 +23151,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 +23186,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 +23224,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 +23268,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 +24062,26 @@ 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 { + typeParameters := core.Map(node.AsQuantifiedTypeNode().TypeParameters.Nodes, func(typeParameterNode *ast.Node) *Type { + return c.getDeclaredTypeOfTypeParameter(typeParameterNode.Symbol()) + }) + newTypeParameters := core.Map(typeParameters, func(tp *Type) *Type { + newTp := c.cloneTypeParameter(tp) + newTp.objectFlags |= ObjectFlagsQuantifiedTypeParameter + return newTp + }) + mapper := newTypeMapper(typeParameters, newTypeParameters) + links.resolvedType = c.newQuantifiedType( + core.Map(c.instantiateTypes(typeParameters, mapper), func(t *Type) *TypeParameter { return t.AsTypeParameter() }), + c.instantiateType(c.getTypeFromTypeNode(node.AsQuantifiedTypeNode().BaseType), mapper), + ) + } + return links.resolvedType +} + func (c *Checker) getIdentifierChain(node *ast.Node) []*ast.Node { if ast.IsIdentifier(node) { return []*ast.Node{node} @@ -24545,6 +24673,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, ObjectFlagsContainsQuantifiedType, 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 +26816,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 +29814,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 332a72569e7..4cbbc1f6edd 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 9bf61948b98..f6f18c85bda 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 1fb4c357942..8d0bdc1fa9e 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 bf65552c7f3..0a90939ba29 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 } @@ -4672,12 +4723,17 @@ func (r *Relater) reportErrorResults(originalSource *Type, originalTarget *Type, } } r.reportRelationError(headMessage, source, target) - if source.flags&TypeFlagsTypeParameter != 0 && source.symbol != nil && len(source.symbol.Declarations) != 0 && r.c.getConstraintOfType(source) == nil { - syntheticParam := r.c.cloneTypeParameter(source) - syntheticParam.AsTypeParameter().constraint = r.c.instantiateType(target, newSimpleTypeMapper(source, syntheticParam)) - if r.c.hasNonCircularBaseConstraint(syntheticParam) { - targetConstraintString := r.c.TypeToString(target) - r.relatedInfo = append(r.relatedInfo, NewDiagnosticForNode(source.symbol.Declarations[0], diagnostics.This_type_parameter_might_need_an_extends_0_constraint, targetConstraintString)) + if source.objectFlags&ObjectFlagsQuantifiedTypeParameter != 0 && target.objectFlags&ObjectFlagsQuantifiedTypeParameter != 0 { + r.relatedInfo = append(r.relatedInfo, NewDiagnosticForNode(source.AsTypeParameter().boundedTo.Declarations[0], diagnostics.Type_parameter_0_is_bounded_to_this_variable, r.c.TypeToString(source))) + r.relatedInfo = append(r.relatedInfo, NewDiagnosticForNode(target.AsTypeParameter().boundedTo.Declarations[0], diagnostics.Type_parameter_0_is_bounded_to_this_variable, r.c.TypeToString(target))) + } else { + if source.flags&TypeFlagsTypeParameter != 0 && source.symbol != nil && len(source.symbol.Declarations) != 0 && r.c.getConstraintOfType(source) == nil { + syntheticParam := r.c.cloneTypeParameter(source) + syntheticParam.AsTypeParameter().constraint = r.c.instantiateType(target, newSimpleTypeMapper(source, syntheticParam)) + if r.c.hasNonCircularBaseConstraint(syntheticParam) { + targetConstraintString := r.c.TypeToString(target) + r.relatedInfo = append(r.relatedInfo, NewDiagnosticForNode(source.symbol.Declarations[0], diagnostics.This_type_parameter_might_need_an_extends_0_constraint, targetConstraintString)) + } } } } @@ -4712,6 +4768,9 @@ func (r *Relater) reportRelationError(message *diagnostics.Message, source *Type r.reportError(diagnostics.X_0_could_be_instantiated_with_an_arbitrary_type_which_could_be_unrelated_to_1, targetType, generalizedSourceType) } } + if target.objectFlags&ObjectFlagsQuantifiedTypeParameter != 0 && generalizedSource.objectFlags&ObjectFlagsQuantifiedTypeParameter != 0 { + r.reportError(diagnostics.Both_type_parameters_are_bounded_to_different_variables) + } if message == nil { switch { case r.relation == r.c.comparableRelation: diff --git a/internal/checker/types.go b/internal/checker/types.go index 3e2aafbd4c3..2d49850e5de 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 @@ -497,10 +498,12 @@ const ( ObjectFlagsCouldContainTypeVariablesComputed ObjectFlags = 1 << 19 // CouldContainTypeVariables flag has been computed ObjectFlagsCouldContainTypeVariables ObjectFlags = 1 << 20 // Type could contain a type variable ObjectFlagsMembersResolved ObjectFlags = 1 << 21 // Members have been resolved + ObjectFlagsContainsQuantifiedType ObjectFlags = 1 << 22 + ObjectFlagsQuantifiedTypeParameter ObjectFlags = 1 << 23 ObjectFlagsClassOrInterface = ObjectFlagsClass | ObjectFlagsInterface ObjectFlagsRequiresWidening = ObjectFlagsContainsWideningType | ObjectFlagsContainsObjectOrArrayLiteral - ObjectFlagsPropagatingFlags = ObjectFlagsContainsWideningType | ObjectFlagsContainsObjectOrArrayLiteral | ObjectFlagsNonInferrableType + ObjectFlagsPropagatingFlags = ObjectFlagsContainsWideningType | ObjectFlagsContainsObjectOrArrayLiteral | ObjectFlagsNonInferrableType | ObjectFlagsContainsQuantifiedType ObjectFlagsInstantiatedMapped = ObjectFlagsMapped | ObjectFlagsInstantiated // Object flags that uniquely identify the kind of ObjectType ObjectFlagsObjectTypeKindMask = ObjectFlagsClassOrInterface | ObjectFlagsReference | ObjectFlagsTuple | ObjectFlagsAnonymous | ObjectFlagsMapped | ObjectFlagsReverseMapped | ObjectFlagsEvolvingArray | ObjectFlagsInstantiationExpressionType | ObjectFlagsSingleSignatureType @@ -594,6 +597,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 @@ -1028,6 +1032,7 @@ type TypeParameter struct { mapper *TypeMapper isThisType bool resolvedDefaultType *Type + boundedTo *ast.Symbol } // IndexFlags @@ -1100,6 +1105,12 @@ type ConditionalType struct { combinedMapper *TypeMapper } +type QuantifiedType struct { + ConstrainedType + typeParameters []*TypeParameter + baseType *Type +} + // SignatureFlags type SignatureFlags uint32 diff --git a/internal/diagnostics/diagnostics_generated.go b/internal/diagnostics/diagnostics_generated.go index 14c2a9b0f48..c39986e2e6b 100644 --- a/internal/diagnostics/diagnostics_generated.go +++ b/internal/diagnostics/diagnostics_generated.go @@ -2362,6 +2362,10 @@ var Visit_https_Colon_Slash_Slashaka_ms_Slashts6_for_migration_information = &Me var X_tsconfig_json_is_present_but_will_not_be_loaded_if_files_are_specified_on_commandline_Use_ignoreConfig_to_skip_this_error = &Message{code: 5112, category: CategoryError, key: "tsconfig_json_is_present_but_will_not_be_loaded_if_files_are_specified_on_commandline_Use_ignoreConf_5112", text: "tsconfig.json is present but will not be loaded if files are specified on commandline. Use '--ignoreConfig' to skip this error."} +var Both_type_parameters_are_bounded_to_different_variables = &Message{code: 5113, category: CategoryError, key: "Both_type_parameters_are_bounded_to_different_variables_5113", text: "Both type parameters are bounded to different variables"} + +var Type_parameter_0_is_bounded_to_this_variable = &Message{code: 5114, category: CategoryError, key: "Type_parameter_0_is_bounded_to_this_variable_5114", text: "Type parameter '{0}' is bounded to this variable"} + var Generates_a_sourcemap_for_each_corresponding_d_ts_file = &Message{code: 6000, category: CategoryMessage, key: "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000", text: "Generates a sourcemap for each corresponding '.d.ts' file."} var Concatenate_and_emit_output_to_single_file = &Message{code: 6001, category: CategoryMessage, key: "Concatenate_and_emit_output_to_single_file_6001", text: "Concatenate and emit output to single file."} @@ -6638,6 +6642,10 @@ func keyToMessage(key Key) *Message { return Visit_https_Colon_Slash_Slashaka_ms_Slashts6_for_migration_information case "tsconfig_json_is_present_but_will_not_be_loaded_if_files_are_specified_on_commandline_Use_ignoreConf_5112": return X_tsconfig_json_is_present_but_will_not_be_loaded_if_files_are_specified_on_commandline_Use_ignoreConfig_to_skip_this_error + case "Both_type_parameters_are_bounded_to_different_variables_5113": + return Both_type_parameters_are_bounded_to_different_variables + case "Type_parameter_0_is_bounded_to_this_variable_5114": + return Type_parameter_0_is_bounded_to_this_variable case "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000": return Generates_a_sourcemap_for_each_corresponding_d_ts_file case "Concatenate_and_emit_output_to_single_file_6001": diff --git a/internal/diagnostics/extraDiagnosticMessages.json b/internal/diagnostics/extraDiagnosticMessages.json index 2566d6ff532..f19c5b6ba12 100644 --- a/internal/diagnostics/extraDiagnosticMessages.json +++ b/internal/diagnostics/extraDiagnosticMessages.json @@ -86,5 +86,13 @@ "Option '{0}' requires value to be greater than '{1}'.": { "category": "Error", "code": 5002 + }, + "Both type parameters are bounded to different variables": { + "category": "Error", + "code": 5113 + }, + "Type parameter '{0}' is bounded to this variable": { + "category": "Error", + "code": 5114 } } diff --git a/internal/parser/parser.go b/internal/parser/parser.go index 00436c0a1b0..8b982b40b7d 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 fec95a7ab13..b21646cfc46 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 00000000000..94e01d9ba65 --- /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 00000000000..e8ead920d75 --- /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 00000000000..600f750c1de --- /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 00000000000..adeb814c1ce --- /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 00000000000..01246608732 --- /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 00000000000..1fd1571ee0b --- /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 00000000000..b7d1ffad49d --- /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 00000000000..38148ca7e81 --- /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 00000000000..d4bdf87766f --- /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 00000000000..cf4677eeb3b --- /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 00000000000..1908d24f2ac --- /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 00000000000..3e04efef513 --- /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 00000000000..014c66f234e --- /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 00000000000..a5cca619d14 --- /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 00000000000..a5f6f0f448d --- /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/quantifiedTypesBoundedTypeParameters.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesBoundedTypeParameters.errors.txt new file mode 100644 index 00000000000..59b8a943742 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesBoundedTypeParameters.errors.txt @@ -0,0 +1,19 @@ +quantifiedTypesBoundedTypeParameters.ts(6,6): error TS2345: Argument of type 'T' is not assignable to parameter of type 'T'. + Both type parameters are bounded to different variables + 'T' could be instantiated with an arbitrary type which could be unrelated to 'T'. + + +==== quantifiedTypesBoundedTypeParameters.ts (1 errors) ==== + type F = { v: T, f: (v: T) => void }; + declare let f1: F + declare let f2: F + + f1.f(f1.v) + f1.f(f2.v) + ~~~~ +!!! error TS2345: Argument of type 'T' is not assignable to parameter of type 'T'. +!!! error TS2345: Both type parameters are bounded to different variables +!!! error TS2345: 'T' could be instantiated with an arbitrary type which could be unrelated to 'T'. +!!! related TS5114 quantifiedTypesBoundedTypeParameters.ts:3:13: Type parameter 'T' is bounded to this variable +!!! related TS5114 quantifiedTypesBoundedTypeParameters.ts:2:13: Type parameter 'T' is bounded to this variable + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesBoundedTypeParameters.js b/testdata/baselines/reference/compiler/quantifiedTypesBoundedTypeParameters.js new file mode 100644 index 00000000000..4b00a72d0b3 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesBoundedTypeParameters.js @@ -0,0 +1,14 @@ +//// [tests/cases/compiler/quantifiedTypesBoundedTypeParameters.ts] //// + +//// [quantifiedTypesBoundedTypeParameters.ts] +type F = { v: T, f: (v: T) => void }; +declare let f1: F +declare let f2: F + +f1.f(f1.v) +f1.f(f2.v) + + +//// [quantifiedTypesBoundedTypeParameters.js] +f1.f(f1.v); +f1.f(f2.v); diff --git a/testdata/baselines/reference/compiler/quantifiedTypesBoundedTypeParameters.symbols b/testdata/baselines/reference/compiler/quantifiedTypesBoundedTypeParameters.symbols new file mode 100644 index 00000000000..f56b3f519f2 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesBoundedTypeParameters.symbols @@ -0,0 +1,36 @@ +//// [tests/cases/compiler/quantifiedTypesBoundedTypeParameters.ts] //// + +=== quantifiedTypesBoundedTypeParameters.ts === +type F = { v: T, f: (v: T) => void }; +>F : Symbol(F, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 0)) +>T : Symbol(T, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 10)) +>v : Symbol(v, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 14)) +>T : Symbol(T, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 10)) +>f : Symbol(f, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 20)) +>v : Symbol(v, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 25)) +>T : Symbol(T, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 10)) + +declare let f1: F +>f1 : Symbol(f1, Decl(quantifiedTypesBoundedTypeParameters.ts, 1, 11)) +>F : Symbol(F, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 0)) + +declare let f2: F +>f2 : Symbol(f2, Decl(quantifiedTypesBoundedTypeParameters.ts, 2, 11)) +>F : Symbol(F, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 0)) + +f1.f(f1.v) +>f1.f : Symbol(f, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 20)) +>f1 : Symbol(f1, Decl(quantifiedTypesBoundedTypeParameters.ts, 1, 11)) +>f : Symbol(f, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 20)) +>f1.v : Symbol(v, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 14)) +>f1 : Symbol(f1, Decl(quantifiedTypesBoundedTypeParameters.ts, 1, 11)) +>v : Symbol(v, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 14)) + +f1.f(f2.v) +>f1.f : Symbol(f, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 20)) +>f1 : Symbol(f1, Decl(quantifiedTypesBoundedTypeParameters.ts, 1, 11)) +>f : Symbol(f, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 20)) +>f2.v : Symbol(v, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 14)) +>f2 : Symbol(f2, Decl(quantifiedTypesBoundedTypeParameters.ts, 2, 11)) +>v : Symbol(v, Decl(quantifiedTypesBoundedTypeParameters.ts, 0, 14)) + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesBoundedTypeParameters.types b/testdata/baselines/reference/compiler/quantifiedTypesBoundedTypeParameters.types new file mode 100644 index 00000000000..e5689db2d92 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesBoundedTypeParameters.types @@ -0,0 +1,33 @@ +//// [tests/cases/compiler/quantifiedTypesBoundedTypeParameters.ts] //// + +=== quantifiedTypesBoundedTypeParameters.ts === +type F = { v: T, f: (v: T) => void }; +>F : { v: T; f: (v: T) => void; } +>v : T +>f : (v: T) => void +>v : T + +declare let f1: F +>f1 : { v: T; f: (v: T) => void; } + +declare let f2: F +>f2 : { v: T; f: (v: T) => void; } + +f1.f(f1.v) +>f1.f(f1.v) : void +>f1.f : (v: T) => void +>f1 : { v: T; f: (v: T) => void; } +>f : (v: T) => void +>f1.v : T +>f1 : { v: T; f: (v: T) => void; } +>v : T + +f1.f(f2.v) +>f1.f(f2.v) : void +>f1.f : (v: T) => void +>f1 : { v: T; f: (v: T) => void; } +>f : (v: T) => void +>f2.v : T +>f2 : { v: T; f: (v: T) => void; } +>v : T + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesConstraints.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesConstraints.errors.txt new file mode 100644 index 00000000000..709c2fa0a56 --- /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 00000000000..957017a7b0c --- /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 00000000000..3099c513f40 --- /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 00000000000..82d96e3f353 --- /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/quantifiedTypesCorrelatedUnions1.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesCorrelatedUnions1.errors.txt new file mode 100644 index 00000000000..993ff8708df --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesCorrelatedUnions1.errors.txt @@ -0,0 +1,28 @@ +quantifiedTypesCorrelatedUnions1.ts(11,11): error TS2322: Type '(num: number) => void' is not assignable to type '(t: string) => void'. + Types of parameters 'num' and 't' are incompatible. + Type 'string' is not assignable to type 'number'. + + +==== quantifiedTypesCorrelatedUnions1.ts (1 errors) ==== + // https://github.com/microsoft/TypeScript/issues/30581#issuecomment-493492463 + + declare const str: string; + declare const num: number; + function acceptString(str: string) { } + function acceptNumber(num: number) { } + + const arr: ( [T, (t: NoInfer) => void])[] = [ + [str, acceptString], + [num, acceptNumber], + [str, acceptNumber], // error as expected + ~~~~~~~~~~~~ +!!! error TS2322: Type '(num: number) => void' is not assignable to type '(t: string) => void'. +!!! error TS2322: Types of parameters 'num' and 't' are incompatible. +!!! error TS2322: Type 'string' is not assignable to type 'number'. + ]; + + for (const pair of arr) { + const [arg, func] = pair; + func(arg); // no error + } + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesCorrelatedUnions1.js b/testdata/baselines/reference/compiler/quantifiedTypesCorrelatedUnions1.js new file mode 100644 index 00000000000..fc56e482657 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesCorrelatedUnions1.js @@ -0,0 +1,35 @@ +//// [tests/cases/compiler/quantifiedTypesCorrelatedUnions1.ts] //// + +//// [quantifiedTypesCorrelatedUnions1.ts] +// https://github.com/microsoft/TypeScript/issues/30581#issuecomment-493492463 + +declare const str: string; +declare const num: number; +function acceptString(str: string) { } +function acceptNumber(num: number) { } + +const arr: ( [T, (t: NoInfer) => void])[] = [ + [str, acceptString], + [num, acceptNumber], + [str, acceptNumber], // error as expected +]; + +for (const pair of arr) { + const [arg, func] = pair; + func(arg); // no error +} + + +//// [quantifiedTypesCorrelatedUnions1.js] +// https://github.com/microsoft/TypeScript/issues/30581#issuecomment-493492463 +function acceptString(str) { } +function acceptNumber(num) { } +const arr = [ + [str, acceptString], + [num, acceptNumber], + [str, acceptNumber], // error as expected +]; +for (const pair of arr) { + const [arg, func] = pair; + func(arg); // no error +} diff --git a/testdata/baselines/reference/compiler/quantifiedTypesCorrelatedUnions1.symbols b/testdata/baselines/reference/compiler/quantifiedTypesCorrelatedUnions1.symbols new file mode 100644 index 00000000000..e3e8cec7a9c --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesCorrelatedUnions1.symbols @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/quantifiedTypesCorrelatedUnions1.ts] //// + +=== quantifiedTypesCorrelatedUnions1.ts === +// https://github.com/microsoft/TypeScript/issues/30581#issuecomment-493492463 + +declare const str: string; +>str : Symbol(str, Decl(quantifiedTypesCorrelatedUnions1.ts, 2, 13)) + +declare const num: number; +>num : Symbol(num, Decl(quantifiedTypesCorrelatedUnions1.ts, 3, 13)) + +function acceptString(str: string) { } +>acceptString : Symbol(acceptString, Decl(quantifiedTypesCorrelatedUnions1.ts, 3, 26)) +>str : Symbol(str, Decl(quantifiedTypesCorrelatedUnions1.ts, 4, 22)) + +function acceptNumber(num: number) { } +>acceptNumber : Symbol(acceptNumber, Decl(quantifiedTypesCorrelatedUnions1.ts, 4, 38)) +>num : Symbol(num, Decl(quantifiedTypesCorrelatedUnions1.ts, 5, 22)) + +const arr: ( [T, (t: NoInfer) => void])[] = [ +>arr : Symbol(arr, Decl(quantifiedTypesCorrelatedUnions1.ts, 7, 5)) +>T : Symbol(T, Decl(quantifiedTypesCorrelatedUnions1.ts, 7, 13)) +>T : Symbol(T, Decl(quantifiedTypesCorrelatedUnions1.ts, 7, 13)) +>t : Symbol(t, Decl(quantifiedTypesCorrelatedUnions1.ts, 7, 21)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(quantifiedTypesCorrelatedUnions1.ts, 7, 13)) + + [str, acceptString], +>str : Symbol(str, Decl(quantifiedTypesCorrelatedUnions1.ts, 2, 13)) +>acceptString : Symbol(acceptString, Decl(quantifiedTypesCorrelatedUnions1.ts, 3, 26)) + + [num, acceptNumber], +>num : Symbol(num, Decl(quantifiedTypesCorrelatedUnions1.ts, 3, 13)) +>acceptNumber : Symbol(acceptNumber, Decl(quantifiedTypesCorrelatedUnions1.ts, 4, 38)) + + [str, acceptNumber], // error as expected +>str : Symbol(str, Decl(quantifiedTypesCorrelatedUnions1.ts, 2, 13)) +>acceptNumber : Symbol(acceptNumber, Decl(quantifiedTypesCorrelatedUnions1.ts, 4, 38)) + +]; + +for (const pair of arr) { +>pair : Symbol(pair, Decl(quantifiedTypesCorrelatedUnions1.ts, 13, 10)) +>arr : Symbol(arr, Decl(quantifiedTypesCorrelatedUnions1.ts, 7, 5)) + + const [arg, func] = pair; +>arg : Symbol(arg, Decl(quantifiedTypesCorrelatedUnions1.ts, 14, 11)) +>func : Symbol(func, Decl(quantifiedTypesCorrelatedUnions1.ts, 14, 15)) +>pair : Symbol(pair, Decl(quantifiedTypesCorrelatedUnions1.ts, 13, 10)) + + func(arg); // no error +>func : Symbol(func, Decl(quantifiedTypesCorrelatedUnions1.ts, 14, 15)) +>arg : Symbol(arg, Decl(quantifiedTypesCorrelatedUnions1.ts, 14, 11)) +} + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesCorrelatedUnions1.types b/testdata/baselines/reference/compiler/quantifiedTypesCorrelatedUnions1.types new file mode 100644 index 00000000000..9dc1ebbb859 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesCorrelatedUnions1.types @@ -0,0 +1,56 @@ +//// [tests/cases/compiler/quantifiedTypesCorrelatedUnions1.ts] //// + +=== quantifiedTypesCorrelatedUnions1.ts === +// https://github.com/microsoft/TypeScript/issues/30581#issuecomment-493492463 + +declare const str: string; +>str : string + +declare const num: number; +>num : number + +function acceptString(str: string) { } +>acceptString : (str: string) => void +>str : string + +function acceptNumber(num: number) { } +>acceptNumber : (num: number) => void +>num : number + +const arr: ( [T, (t: NoInfer) => void])[] = [ +>arr : ( [T, (t: NoInfer) => void])[] +>t : NoInfer +>[ [str, acceptString], [num, acceptNumber], [str, acceptNumber], // error as expected] : any[] + + [str, acceptString], +>[str, acceptString] : [string, (str: string) => void] +>str : string +>acceptString : (str: string) => void + + [num, acceptNumber], +>[num, acceptNumber] : [number, (num: number) => void] +>num : number +>acceptNumber : (num: number) => void + + [str, acceptNumber], // error as expected +>[str, acceptNumber] : any +>str : string +>acceptNumber : (num: number) => void + +]; + +for (const pair of arr) { +>pair : [T, (t: NoInfer) => void] +>arr : ( [T, (t: NoInfer) => void])[] + + const [arg, func] = pair; +>arg : T +>func : (t: NoInfer) => void +>pair : [T, (t: NoInfer) => void] + + func(arg); // no error +>func(arg) : void +>func : (t: NoInfer) => void +>arg : T +} + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesIntermediate.errors.txt new file mode 100644 index 00000000000..7a19c688849 --- /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 00000000000..eb438b60786 --- /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 00000000000..382b53bd891 --- /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 00000000000..3adbdf63e71 --- /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 00000000000..49820d3d452 --- /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 00000000000..a0bc31d741a --- /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 00000000000..1ff71c460c6 --- /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 00000000000..a056d39039d --- /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 00000000000..3a786df7987 --- /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 00000000000..0a7a9c737a7 --- /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 00000000000..4dd5c97fed2 --- /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 00000000000..298ef126339 --- /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 00000000000..b65ea49e8bf --- /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 00000000000..2ce8c87df19 --- /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 00000000000..bf2cb764c76 --- /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 00000000000..ab66b8caf47 --- /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 00000000000..e9cc9744c50 --- /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/quantifiedTypesParentInferenceContext4.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext4.errors.txt new file mode 100644 index 00000000000..f4e36726619 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext4.errors.txt @@ -0,0 +1,59 @@ +quantifiedTypesParentInferenceContext4.ts(19,16): error TS2698: Spread types may only be created from object types. +quantifiedTypesParentInferenceContext4.ts(19,28): error TS2339: Property 'b' does not exist on type 'unknown'. +quantifiedTypesParentInferenceContext4.ts(22,15): error TS2698: Spread types may only be created from object types. + + +==== quantifiedTypesParentInferenceContext4.ts (3 errors) ==== + declare const f: + (x: + { + a: () => A, + ab: (a: A) => B, + nested: { + c: (b: B) => C, + cd: (c: C) => D, + }, + de: (d: D) => E + } + ) => void + + // TODO: this should compile just like the f1 call + f({ + a: () => ({ a: 0 }), + ab: x => ({ ...x, b: "" }), + nested: { + c: x => ({ ...x, c: +x.b }), + ~~~~ +!!! error TS2698: Spread types may only be created from object types. + ~ +!!! error TS2339: Property 'b' does not exist on type 'unknown'. + cd: x => ({ ...x, d: Boolean(x.c) }) + }, + de: x => ({ ...x, e: "" }) + ~~~~ +!!! error TS2698: Spread types may only be created from object types. + }) + + declare const f1: + + (x: + { + a: () => A, + ab: (a: A) => B, + nested: { + c: (b: B) => C, + cd: (c: C) => D, + }, + de: (d: D) => E + } + ) => void + + f1({ + a: () => ({ a: 0 }), + ab: x => ({ ...x, b: "" }), + nested: { + c: x => ({ ...x, c: +x.b }), + cd: x => ({ ...x, d: Boolean(x.c) }) + }, + de: x => ({ ...x, e: "" }) + }) \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext4.js b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext4.js new file mode 100644 index 00000000000..3e30236a66a --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext4.js @@ -0,0 +1,71 @@ +//// [tests/cases/compiler/quantifiedTypesParentInferenceContext4.ts] //// + +//// [quantifiedTypesParentInferenceContext4.ts] +declare const f: + (x: + { + a: () => A, + ab: (a: A) => B, + nested: { + c: (b: B) => C, + cd: (c: C) => D, + }, + de: (d: D) => E + } + ) => void + +// TODO: this should compile just like the f1 call +f({ + a: () => ({ a: 0 }), + ab: x => ({ ...x, b: "" }), + nested: { + c: x => ({ ...x, c: +x.b }), + cd: x => ({ ...x, d: Boolean(x.c) }) + }, + de: x => ({ ...x, e: "" }) +}) + +declare const f1: + + (x: + { + a: () => A, + ab: (a: A) => B, + nested: { + c: (b: B) => C, + cd: (c: C) => D, + }, + de: (d: D) => E + } + ) => void + +f1({ + a: () => ({ a: 0 }), + ab: x => ({ ...x, b: "" }), + nested: { + c: x => ({ ...x, c: +x.b }), + cd: x => ({ ...x, d: Boolean(x.c) }) + }, + de: x => ({ ...x, e: "" }) +}) + +//// [quantifiedTypesParentInferenceContext4.js] +// TODO: this should compile just like the f1 call +f({ + a: () => ({ a: 0 }), + ab: x => (Object.assign(Object.assign({}, x), { b: "" })), + nested: { + c: x => (Object.assign(Object.assign({}, x), { c: +x.b })), + cd: x => (Object.assign(Object.assign({}, x), { d: Boolean(x.c) })) + }, + de: x => (Object.assign(Object.assign({}, x), { e: "" })) +}); +f1({ + a: () => ({ a: 0 }), + ab: x => (Object.assign(Object.assign({}, x), { b: "" })), + nested: { + c: x => (Object.assign(Object.assign({}, x), { c: +x.b })), + cd: x => (Object.assign(Object.assign({}, x), { d: Boolean(x.c) })) + }, + de: x => (Object.assign(Object.assign({}, x), { e: "" })) +}); diff --git a/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext4.symbols b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext4.symbols new file mode 100644 index 00000000000..388aff3e9df --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext4.symbols @@ -0,0 +1,181 @@ +//// [tests/cases/compiler/quantifiedTypesParentInferenceContext4.ts] //// + +=== quantifiedTypesParentInferenceContext4.ts === +declare const f: +>f : Symbol(f, Decl(quantifiedTypesParentInferenceContext4.ts, 0, 13)) + + (x: +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 1, 3)) + + { +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext4.ts, 2, 5)) +>B : Symbol(B, Decl(quantifiedTypesParentInferenceContext4.ts, 2, 7)) +>D : Symbol(D, Decl(quantifiedTypesParentInferenceContext4.ts, 2, 10)) +>E : Symbol(E, Decl(quantifiedTypesParentInferenceContext4.ts, 2, 13)) + + a: () => A, +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext4.ts, 2, 18)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext4.ts, 2, 5)) + + ab: (a: A) => B, +>ab : Symbol(ab, Decl(quantifiedTypesParentInferenceContext4.ts, 3, 17)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext4.ts, 4, 11)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext4.ts, 2, 5)) +>B : Symbol(B, Decl(quantifiedTypesParentInferenceContext4.ts, 2, 7)) + + nested: { +>nested : Symbol(nested, Decl(quantifiedTypesParentInferenceContext4.ts, 4, 22)) +>C : Symbol(C, Decl(quantifiedTypesParentInferenceContext4.ts, 5, 15)) + + c: (b: B) => C, +>c : Symbol(c, Decl(quantifiedTypesParentInferenceContext4.ts, 5, 19)) +>b : Symbol(b, Decl(quantifiedTypesParentInferenceContext4.ts, 6, 12)) +>B : Symbol(B, Decl(quantifiedTypesParentInferenceContext4.ts, 2, 7)) +>C : Symbol(C, Decl(quantifiedTypesParentInferenceContext4.ts, 5, 15)) + + cd: (c: C) => D, +>cd : Symbol(cd, Decl(quantifiedTypesParentInferenceContext4.ts, 6, 23)) +>c : Symbol(c, Decl(quantifiedTypesParentInferenceContext4.ts, 7, 13)) +>C : Symbol(C, Decl(quantifiedTypesParentInferenceContext4.ts, 5, 15)) +>D : Symbol(D, Decl(quantifiedTypesParentInferenceContext4.ts, 2, 10)) + + }, + de: (d: D) => E +>de : Symbol(de, Decl(quantifiedTypesParentInferenceContext4.ts, 8, 8)) +>d : Symbol(d, Decl(quantifiedTypesParentInferenceContext4.ts, 9, 11)) +>D : Symbol(D, Decl(quantifiedTypesParentInferenceContext4.ts, 2, 10)) +>E : Symbol(E, Decl(quantifiedTypesParentInferenceContext4.ts, 2, 13)) + } + ) => void + +// TODO: this should compile just like the f1 call +f({ +>f : Symbol(f, Decl(quantifiedTypesParentInferenceContext4.ts, 0, 13)) + + a: () => ({ a: 0 }), +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext4.ts, 14, 3)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext4.ts, 15, 13)) + + ab: x => ({ ...x, b: "" }), +>ab : Symbol(ab, Decl(quantifiedTypesParentInferenceContext4.ts, 15, 22)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 16, 5)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 16, 5)) +>b : Symbol(b, Decl(quantifiedTypesParentInferenceContext4.ts, 16, 19)) + + nested: { +>nested : Symbol(nested, Decl(quantifiedTypesParentInferenceContext4.ts, 16, 29)) + + c: x => ({ ...x, c: +x.b }), +>c : Symbol(c, Decl(quantifiedTypesParentInferenceContext4.ts, 17, 11)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 18, 6)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 18, 6)) +>c : Symbol(c, Decl(quantifiedTypesParentInferenceContext4.ts, 18, 20)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 18, 6)) + + cd: x => ({ ...x, d: Boolean(x.c) }) +>cd : Symbol(cd, Decl(quantifiedTypesParentInferenceContext4.ts, 18, 32)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 19, 7)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 19, 7)) +>d : Symbol(d, Decl(quantifiedTypesParentInferenceContext4.ts, 19, 21)) +>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 19, 7)) + + }, + de: x => ({ ...x, e: "" }) +>de : Symbol(de, Decl(quantifiedTypesParentInferenceContext4.ts, 20, 4)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 21, 5)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 21, 5)) +>e : Symbol(e, Decl(quantifiedTypesParentInferenceContext4.ts, 21, 19)) + +}) + +declare const f1: +>f1 : Symbol(f1, Decl(quantifiedTypesParentInferenceContext4.ts, 24, 13)) + + +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 3)) +>B : Symbol(B, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 5)) +>C : Symbol(C, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 8)) +>D : Symbol(D, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 11)) +>E : Symbol(E, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 14)) + + (x: +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 26, 3)) + { + a: () => A, +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext4.ts, 27, 6)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 3)) + + ab: (a: A) => B, +>ab : Symbol(ab, Decl(quantifiedTypesParentInferenceContext4.ts, 28, 17)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext4.ts, 29, 11)) +>A : Symbol(A, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 3)) +>B : Symbol(B, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 5)) + + nested: { +>nested : Symbol(nested, Decl(quantifiedTypesParentInferenceContext4.ts, 29, 22)) + + c: (b: B) => C, +>c : Symbol(c, Decl(quantifiedTypesParentInferenceContext4.ts, 30, 15)) +>b : Symbol(b, Decl(quantifiedTypesParentInferenceContext4.ts, 31, 12)) +>B : Symbol(B, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 5)) +>C : Symbol(C, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 8)) + + cd: (c: C) => D, +>cd : Symbol(cd, Decl(quantifiedTypesParentInferenceContext4.ts, 31, 23)) +>c : Symbol(c, Decl(quantifiedTypesParentInferenceContext4.ts, 32, 13)) +>C : Symbol(C, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 8)) +>D : Symbol(D, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 11)) + + }, + de: (d: D) => E +>de : Symbol(de, Decl(quantifiedTypesParentInferenceContext4.ts, 33, 8)) +>d : Symbol(d, Decl(quantifiedTypesParentInferenceContext4.ts, 34, 11)) +>D : Symbol(D, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 11)) +>E : Symbol(E, Decl(quantifiedTypesParentInferenceContext4.ts, 25, 14)) + } + ) => void + +f1({ +>f1 : Symbol(f1, Decl(quantifiedTypesParentInferenceContext4.ts, 24, 13)) + + a: () => ({ a: 0 }), +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext4.ts, 38, 4)) +>a : Symbol(a, Decl(quantifiedTypesParentInferenceContext4.ts, 39, 13)) + + ab: x => ({ ...x, b: "" }), +>ab : Symbol(ab, Decl(quantifiedTypesParentInferenceContext4.ts, 39, 22)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 40, 5)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 40, 5)) +>b : Symbol(b, Decl(quantifiedTypesParentInferenceContext4.ts, 40, 19)) + + nested: { +>nested : Symbol(nested, Decl(quantifiedTypesParentInferenceContext4.ts, 40, 29)) + + c: x => ({ ...x, c: +x.b }), +>c : Symbol(c, Decl(quantifiedTypesParentInferenceContext4.ts, 41, 11)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 42, 6)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 42, 6)) +>c : Symbol(c, Decl(quantifiedTypesParentInferenceContext4.ts, 42, 20)) +>x.b : Symbol(b, Decl(quantifiedTypesParentInferenceContext4.ts, 40, 19)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 42, 6)) +>b : Symbol(b, Decl(quantifiedTypesParentInferenceContext4.ts, 40, 19)) + + cd: x => ({ ...x, d: Boolean(x.c) }) +>cd : Symbol(cd, Decl(quantifiedTypesParentInferenceContext4.ts, 42, 32)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 43, 7)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 43, 7)) +>d : Symbol(d, Decl(quantifiedTypesParentInferenceContext4.ts, 43, 21)) +>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>x.c : Symbol(c, Decl(quantifiedTypesParentInferenceContext4.ts, 42, 20)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 43, 7)) +>c : Symbol(c, Decl(quantifiedTypesParentInferenceContext4.ts, 42, 20)) + + }, + de: x => ({ ...x, e: "" }) +>de : Symbol(de, Decl(quantifiedTypesParentInferenceContext4.ts, 44, 4)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 45, 5)) +>x : Symbol(x, Decl(quantifiedTypesParentInferenceContext4.ts, 45, 5)) +>e : Symbol(e, Decl(quantifiedTypesParentInferenceContext4.ts, 45, 19)) + +}) diff --git a/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext4.types b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext4.types new file mode 100644 index 00000000000..d4ef97110d4 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesParentInferenceContext4.types @@ -0,0 +1,201 @@ +//// [tests/cases/compiler/quantifiedTypesParentInferenceContext4.ts] //// + +=== quantifiedTypesParentInferenceContext4.ts === +declare const f: +>f : (x: { a: () => A; ab: (a: A) => B; nested: { c: (b: B) => C; cd: (c: C) => D; }; de: (d: D) => E; }) => void + + (x: +>x : { a: () => A; ab: (a: A) => B; nested: { c: (b: B) => C; cd: (c: C) => D; }; de: (d: D) => E; } + + { + a: () => A, +>a : () => A + + ab: (a: A) => B, +>ab : (a: A) => B +>a : A + + nested: { +>nested : { c: (b: B) => C; cd: (c: C) => D; } + + c: (b: B) => C, +>c : (b: B) => C +>b : B + + cd: (c: C) => D, +>cd : (c: C) => D +>c : C + + }, + de: (d: D) => E +>de : (d: D) => E +>d : D + } + ) => void + +// TODO: this should compile just like the f1 call +f({ +>f({ a: () => ({ a: 0 }), ab: x => ({ ...x, b: "" }), nested: { c: x => ({ ...x, c: +x.b }), cd: x => ({ ...x, d: Boolean(x.c) }) }, de: x => ({ ...x, e: "" })}) : void +>f : (x: { a: () => A; ab: (a: A) => B; nested: { c: (b: B) => C; cd: (c: C) => D; }; de: (d: D) => E; }) => void +>{ a: () => ({ a: 0 }), ab: x => ({ ...x, b: "" }), nested: { c: x => ({ ...x, c: +x.b }), cd: x => ({ ...x, d: Boolean(x.c) }) }, de: x => ({ ...x, e: "" })} : { a: () => { a: number; }; ab: (x: { a: number; }) => { a: number; b: string; }; nested: { c: (x: unknown) => any; cd: (x: any) => any; }; de: (x: unknown) => any; } + + a: () => ({ a: 0 }), +>a : () => { a: number; } +>() => ({ a: 0 }) : () => { a: number; } +>({ a: 0 }) : { a: number; } +>{ a: 0 } : { a: number; } +>a : number +>0 : 0 + + ab: x => ({ ...x, b: "" }), +>ab : (x: { a: number; }) => { a: number; b: string; } +>x => ({ ...x, b: "" }) : (x: { a: number; }) => { a: number; b: string; } +>x : { a: number; } +>({ ...x, b: "" }) : { a: number; b: string; } +>{ ...x, b: "" } : { a: number; b: string; } +>x : { a: number; } +>b : string +>"" : "" + + nested: { +>nested : { c: (x: unknown) => any; cd: (x: any) => any; } +>{ c: x => ({ ...x, c: +x.b }), cd: x => ({ ...x, d: Boolean(x.c) }) } : { c: (x: unknown) => any; cd: (x: any) => any; } + + c: x => ({ ...x, c: +x.b }), +>c : (x: unknown) => any +>x => ({ ...x, c: +x.b }) : (x: unknown) => any +>x : unknown +>({ ...x, c: +x.b }) : any +>{ ...x, c: +x.b } : any +>x : unknown +>c : number +>+x.b : number +>x.b : any +>x : unknown +>b : any + + cd: x => ({ ...x, d: Boolean(x.c) }) +>cd : (x: any) => any +>x => ({ ...x, d: Boolean(x.c) }) : (x: any) => any +>x : any +>({ ...x, d: Boolean(x.c) }) : any +>{ ...x, d: Boolean(x.c) } : any +>x : any +>d : boolean +>Boolean(x.c) : boolean +>Boolean : BooleanConstructor +>x.c : any +>x : any +>c : any + + }, + de: x => ({ ...x, e: "" }) +>de : (x: unknown) => any +>x => ({ ...x, e: "" }) : (x: unknown) => any +>x : unknown +>({ ...x, e: "" }) : any +>{ ...x, e: "" } : any +>x : unknown +>e : string +>"" : "" + +}) + +declare const f1: +>f1 : (x: { a: () => A; ab: (a: A) => B; nested: { c: (b: B) => C; cd: (c: C) => D; }; de: (d: D) => E; }) => void + + + (x: +>x : { a: () => A; ab: (a: A) => B; nested: { c: (b: B) => C; cd: (c: C) => D; }; de: (d: D) => E; } + { + a: () => A, +>a : () => A + + ab: (a: A) => B, +>ab : (a: A) => B +>a : A + + nested: { +>nested : { c: (b: B) => C; cd: (c: C) => D; } + + c: (b: B) => C, +>c : (b: B) => C +>b : B + + cd: (c: C) => D, +>cd : (c: C) => D +>c : C + + }, + de: (d: D) => E +>de : (d: D) => E +>d : D + } + ) => void + +f1({ +>f1({ a: () => ({ a: 0 }), ab: x => ({ ...x, b: "" }), nested: { c: x => ({ ...x, c: +x.b }), cd: x => ({ ...x, d: Boolean(x.c) }) }, de: x => ({ ...x, e: "" })}) : void +>f1 : (x: { a: () => A; ab: (a: A) => B; nested: { c: (b: B) => C; cd: (c: C) => D; }; de: (d: D) => E; }) => void +>{ a: () => ({ a: 0 }), ab: x => ({ ...x, b: "" }), nested: { c: x => ({ ...x, c: +x.b }), cd: x => ({ ...x, d: Boolean(x.c) }) }, de: x => ({ ...x, e: "" })} : { a: () => { a: number; }; ab: (x: { a: number; }) => { a: number; b: string; }; nested: { c: (x: { a: number; b: string; }) => { a: number; b: string; c: number; }; cd: (x: { a: number; b: string; c: number; }) => { a: number; b: string; c: number; d: boolean; }; }; de: (x: { a: number; b: string; c: number; d: boolean; }) => { a: number; b: string; c: number; d: boolean; e: string; }; } + + a: () => ({ a: 0 }), +>a : () => { a: number; } +>() => ({ a: 0 }) : () => { a: number; } +>({ a: 0 }) : { a: number; } +>{ a: 0 } : { a: number; } +>a : number +>0 : 0 + + ab: x => ({ ...x, b: "" }), +>ab : (x: { a: number; }) => { a: number; b: string; } +>x => ({ ...x, b: "" }) : (x: { a: number; }) => { a: number; b: string; } +>x : { a: number; } +>({ ...x, b: "" }) : { a: number; b: string; } +>{ ...x, b: "" } : { a: number; b: string; } +>x : { a: number; } +>b : string +>"" : "" + + nested: { +>nested : { c: (x: { a: number; b: string; }) => { a: number; b: string; c: number; }; cd: (x: { a: number; b: string; c: number; }) => { a: number; b: string; c: number; d: boolean; }; } +>{ c: x => ({ ...x, c: +x.b }), cd: x => ({ ...x, d: Boolean(x.c) }) } : { c: (x: { a: number; b: string; }) => { a: number; b: string; c: number; }; cd: (x: { a: number; b: string; c: number; }) => { a: number; b: string; c: number; d: boolean; }; } + + c: x => ({ ...x, c: +x.b }), +>c : (x: { a: number; b: string; }) => { a: number; b: string; c: number; } +>x => ({ ...x, c: +x.b }) : (x: { a: number; b: string; }) => { a: number; b: string; c: number; } +>x : { a: number; b: string; } +>({ ...x, c: +x.b }) : { a: number; b: string; c: number; } +>{ ...x, c: +x.b } : { a: number; b: string; c: number; } +>x : { a: number; b: string; } +>c : number +>+x.b : number +>x.b : string +>x : { a: number; b: string; } +>b : string + + cd: x => ({ ...x, d: Boolean(x.c) }) +>cd : (x: { a: number; b: string; c: number; }) => { a: number; b: string; c: number; d: boolean; } +>x => ({ ...x, d: Boolean(x.c) }) : (x: { a: number; b: string; c: number; }) => { a: number; b: string; c: number; d: boolean; } +>x : { a: number; b: string; c: number; } +>({ ...x, d: Boolean(x.c) }) : { a: number; b: string; c: number; d: boolean; } +>{ ...x, d: Boolean(x.c) } : { a: number; b: string; c: number; d: boolean; } +>x : { a: number; b: string; c: number; } +>d : boolean +>Boolean(x.c) : boolean +>Boolean : BooleanConstructor +>x.c : number +>x : { a: number; b: string; c: number; } +>c : number + + }, + de: x => ({ ...x, e: "" }) +>de : (x: { a: number; b: string; c: number; d: boolean; }) => { a: number; b: string; c: number; d: boolean; e: string; } +>x => ({ ...x, e: "" }) : (x: { a: number; b: string; c: number; d: boolean; }) => { a: number; b: string; c: number; d: boolean; e: string; } +>x : { a: number; b: string; c: number; d: boolean; } +>({ ...x, e: "" }) : { a: number; b: string; c: number; d: boolean; e: string; } +>{ ...x, e: "" } : { a: number; b: string; c: number; d: boolean; e: string; } +>x : { a: number; b: string; c: number; d: boolean; } +>e : string +>"" : "" + +}) diff --git a/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesReduxToolkit.errors.txt new file mode 100644 index 00000000000..ddc1590c26b --- /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 00000000000..0f1d6da7946 --- /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 00000000000..66f3d99d611 --- /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 00000000000..357dd94445b --- /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 00000000000..7eb9c7328aa --- /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 00000000000..6175a59ba07 --- /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 00000000000..0ce23b02878 --- /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 00000000000..81fd7caee91 --- /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 00000000000..6332d611080 --- /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 00000000000..ac06e2aedbc --- /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 00000000000..3c5167ee4d0 --- /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 00000000000..59bd1d8cb9b --- /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/baselines/reference/compiler/quantifiedTypesUnwrapBaseType.errors.txt b/testdata/baselines/reference/compiler/quantifiedTypesUnwrapBaseType.errors.txt new file mode 100644 index 00000000000..8a15ce4f0d6 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesUnwrapBaseType.errors.txt @@ -0,0 +1,16 @@ +quantifiedTypesUnwrapBaseType.ts(6,5): error TS2345: Argument of type 'number' is not assignable to parameter of type 'T'. + 'T' could be instantiated with an arbitrary type which could be unrelated to 'number'. + + +==== quantifiedTypesUnwrapBaseType.ts (1 errors) ==== + const f = (x: [T, NoInfer]) => { + let [t0, t1] = x + } + + const g = (f: ((t: T) => T)) => { + f(0) + ~ +!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'T'. +!!! error TS2345: 'T' could be instantiated with an arbitrary type which could be unrelated to 'number'. + } + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/quantifiedTypesUnwrapBaseType.js b/testdata/baselines/reference/compiler/quantifiedTypesUnwrapBaseType.js new file mode 100644 index 00000000000..f3beaae75f1 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesUnwrapBaseType.js @@ -0,0 +1,19 @@ +//// [tests/cases/compiler/quantifiedTypesUnwrapBaseType.ts] //// + +//// [quantifiedTypesUnwrapBaseType.ts] +const f = (x: [T, NoInfer]) => { + let [t0, t1] = x +} + +const g = (f: ((t: T) => T)) => { + f(0) +} + + +//// [quantifiedTypesUnwrapBaseType.js] +const f = (x) => { + let [t0, t1] = x; +}; +const g = (f) => { + f(0); +}; diff --git a/testdata/baselines/reference/compiler/quantifiedTypesUnwrapBaseType.symbols b/testdata/baselines/reference/compiler/quantifiedTypesUnwrapBaseType.symbols new file mode 100644 index 00000000000..8593dc78547 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesUnwrapBaseType.symbols @@ -0,0 +1,29 @@ +//// [tests/cases/compiler/quantifiedTypesUnwrapBaseType.ts] //// + +=== quantifiedTypesUnwrapBaseType.ts === +const f = (x: [T, NoInfer]) => { +>f : Symbol(f, Decl(quantifiedTypesUnwrapBaseType.ts, 0, 5)) +>x : Symbol(x, Decl(quantifiedTypesUnwrapBaseType.ts, 0, 11)) +>T : Symbol(T, Decl(quantifiedTypesUnwrapBaseType.ts, 0, 15)) +>T : Symbol(T, Decl(quantifiedTypesUnwrapBaseType.ts, 0, 15)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(quantifiedTypesUnwrapBaseType.ts, 0, 15)) + + let [t0, t1] = x +>t0 : Symbol(t0, Decl(quantifiedTypesUnwrapBaseType.ts, 1, 7)) +>t1 : Symbol(t1, Decl(quantifiedTypesUnwrapBaseType.ts, 1, 10)) +>x : Symbol(x, Decl(quantifiedTypesUnwrapBaseType.ts, 0, 11)) +} + +const g = (f: ((t: T) => T)) => { +>g : Symbol(g, Decl(quantifiedTypesUnwrapBaseType.ts, 4, 5)) +>f : Symbol(f, Decl(quantifiedTypesUnwrapBaseType.ts, 4, 11)) +>T : Symbol(T, Decl(quantifiedTypesUnwrapBaseType.ts, 4, 15)) +>t : Symbol(t, Decl(quantifiedTypesUnwrapBaseType.ts, 4, 20)) +>T : Symbol(T, Decl(quantifiedTypesUnwrapBaseType.ts, 4, 15)) +>T : Symbol(T, Decl(quantifiedTypesUnwrapBaseType.ts, 4, 15)) + + f(0) +>f : Symbol(f, Decl(quantifiedTypesUnwrapBaseType.ts, 4, 11)) +} + diff --git a/testdata/baselines/reference/compiler/quantifiedTypesUnwrapBaseType.types b/testdata/baselines/reference/compiler/quantifiedTypesUnwrapBaseType.types new file mode 100644 index 00000000000..603d38a51c1 --- /dev/null +++ b/testdata/baselines/reference/compiler/quantifiedTypesUnwrapBaseType.types @@ -0,0 +1,26 @@ +//// [tests/cases/compiler/quantifiedTypesUnwrapBaseType.ts] //// + +=== quantifiedTypesUnwrapBaseType.ts === +const f = (x: [T, NoInfer]) => { +>f : (x: [T, NoInfer]) => void +>(x: [T, NoInfer]) => { let [t0, t1] = x} : (x: [T, NoInfer]) => void +>x : [T, NoInfer] + + let [t0, t1] = x +>t0 : T +>t1 : NoInfer +>x : [T, NoInfer] +} + +const g = (f: ((t: T) => T)) => { +>g : (f: (t: T) => T) => void +>(f: ((t: T) => T)) => { f(0)} : (f: (t: T) => T) => void +>f : (t: T) => T +>t : T + + f(0) +>f(0) : T +>f : (t: T) => T +>0 : 0 +} + diff --git a/testdata/tests/cases/compiler/allowQuantifiedTypes.ts b/testdata/tests/cases/compiler/allowQuantifiedTypes.ts new file mode 100644 index 00000000000..2c1b5080f6b --- /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 00000000000..d3ecd39e6d2 --- /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 00000000000..7abdd40a2a6 --- /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 00000000000..adb6a4cfdc8 --- /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/quantifiedTypesBoundedTypeParameters.ts b/testdata/tests/cases/compiler/quantifiedTypesBoundedTypeParameters.ts new file mode 100644 index 00000000000..6e1af86bc45 --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesBoundedTypeParameters.ts @@ -0,0 +1,6 @@ +type F = { v: T, f: (v: T) => void }; +declare let f1: F +declare let f2: F + +f1.f(f1.v) +f1.f(f2.v) diff --git a/testdata/tests/cases/compiler/quantifiedTypesConstraints.ts b/testdata/tests/cases/compiler/quantifiedTypesConstraints.ts new file mode 100644 index 00000000000..e32b1c9dda5 --- /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/quantifiedTypesCorrelatedUnions1.ts b/testdata/tests/cases/compiler/quantifiedTypesCorrelatedUnions1.ts new file mode 100644 index 00000000000..67c01e463b3 --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesCorrelatedUnions1.ts @@ -0,0 +1,17 @@ +// https://github.com/microsoft/TypeScript/issues/30581#issuecomment-493492463 + +declare const str: string; +declare const num: number; +function acceptString(str: string) { } +function acceptNumber(num: number) { } + +const arr: ( [T, (t: NoInfer) => void])[] = [ + [str, acceptString], + [num, acceptNumber], + [str, acceptNumber], // error as expected +]; + +for (const pair of arr) { + const [arg, func] = pair; + func(arg); // no error +} diff --git a/testdata/tests/cases/compiler/quantifiedTypesIntermediate.ts b/testdata/tests/cases/compiler/quantifiedTypesIntermediate.ts new file mode 100644 index 00000000000..b1f0876e06f --- /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 00000000000..5a06230a30a --- /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 00000000000..3fba34c1f1a --- /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 00000000000..ec538b5d506 --- /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 00000000000..168335e035a --- /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/quantifiedTypesParentInferenceContext4.ts b/testdata/tests/cases/compiler/quantifiedTypesParentInferenceContext4.ts new file mode 100644 index 00000000000..aa6fd01e1d1 --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesParentInferenceContext4.ts @@ -0,0 +1,47 @@ +declare const f: + (x: + { + a: () => A, + ab: (a: A) => B, + nested: { + c: (b: B) => C, + cd: (c: C) => D, + }, + de: (d: D) => E + } + ) => void + +// TODO: this should compile just like the f1 call +f({ + a: () => ({ a: 0 }), + ab: x => ({ ...x, b: "" }), + nested: { + c: x => ({ ...x, c: +x.b }), + cd: x => ({ ...x, d: Boolean(x.c) }) + }, + de: x => ({ ...x, e: "" }) +}) + +declare const f1: + + (x: + { + a: () => A, + ab: (a: A) => B, + nested: { + c: (b: B) => C, + cd: (c: C) => D, + }, + de: (d: D) => E + } + ) => void + +f1({ + a: () => ({ a: 0 }), + ab: x => ({ ...x, b: "" }), + nested: { + c: x => ({ ...x, c: +x.b }), + cd: x => ({ ...x, d: Boolean(x.c) }) + }, + de: x => ({ ...x, e: "" }) +}) \ No newline at end of file diff --git a/testdata/tests/cases/compiler/quantifiedTypesReduxToolkit.ts b/testdata/tests/cases/compiler/quantifiedTypesReduxToolkit.ts new file mode 100644 index 00000000000..522a3f52c79 --- /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 00000000000..324a8920bb0 --- /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 00000000000..bd9746035bd --- /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 diff --git a/testdata/tests/cases/compiler/quantifiedTypesUnwrapBaseType.ts b/testdata/tests/cases/compiler/quantifiedTypesUnwrapBaseType.ts new file mode 100644 index 00000000000..3a3cc7a58fa --- /dev/null +++ b/testdata/tests/cases/compiler/quantifiedTypesUnwrapBaseType.ts @@ -0,0 +1,7 @@ +const f = (x: [T, NoInfer]) => { + let [t0, t1] = x +} + +const g = (f: ((t: T) => T)) => { + f(0) +}