Fix JSX contextual types to not eagerly become apparent, use 2-pass inference for JSX (#21383)

* Fix JSX contextual types to not eagerly become apparent

* Apply changes from code review, unify common code

* Fix jsx children contextual typing

* Light code review feedback

* Use fillMissingTypeArguments

* Accept nonliteral jsx child type

* Add test for the fillMissingTypeArguments case
This commit is contained in:
Wesley Wigham 2018-02-05 16:33:39 -08:00 committed by GitHub
parent 3b220a8b0f
commit 17554ff285
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 1033 additions and 152 deletions

View file

@ -14196,56 +14196,35 @@ namespace ts {
return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined;
}
function getContextualTypeForChildJsxExpression(node: JsxElement) {
const attributesType = getApparentTypeOfContextualType(node.openingElement.tagName);
// JSX expression is in children of JSX Element, we will look for an "children" atttribute (we get the name from JSX.ElementAttributesProperty)
const jsxChildrenPropertyName = getJsxElementChildrenPropertyName();
return attributesType && !isTypeAny(attributesType) && jsxChildrenPropertyName && jsxChildrenPropertyName !== "" ? getTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName) : undefined;
}
function getContextualTypeForJsxExpression(node: JsxExpression): Type {
// JSX expression can appear in two position : JSX Element's children or JSX attribute
const jsxAttributes = isJsxAttributeLike(node.parent) ?
node.parent.parent :
isJsxElement(node.parent) ?
node.parent.openingElement.attributes :
undefined; // node.parent is JsxFragment with no attributes
if (!jsxAttributes) {
return undefined; // don't check children of a fragment
}
// When we trying to resolve JsxOpeningLikeElement as a stateless function element, we will already give its attributes a contextual type
// which is a type of the parameter of the signature we are trying out.
// If there is no contextual type (e.g. we are trying to resolve stateful component), get attributes type from resolving element's tagName
const attributesType = getContextualType(jsxAttributes);
if (!attributesType || isTypeAny(attributesType)) {
return undefined;
}
if (isJsxAttribute(node.parent)) {
// JSX expression is in JSX attribute
return getTypeOfPropertyOfContextualType(attributesType, node.parent.name.escapedText);
}
else if (node.parent.kind === SyntaxKind.JsxElement) {
// JSX expression is in children of JSX Element, we will look for an "children" atttribute (we get the name from JSX.ElementAttributesProperty)
const jsxChildrenPropertyName = getJsxElementChildrenPropertyname();
return jsxChildrenPropertyName && jsxChildrenPropertyName !== "" ? getTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName) : anyType;
}
else {
// JSX expression is in JSX spread attribute
return attributesType;
}
const exprParent = node.parent;
return isJsxAttributeLike(exprParent)
? getContextualType(node)
: isJsxElement(exprParent)
? getContextualTypeForChildJsxExpression(exprParent)
: undefined;
}
function getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute) {
// When we trying to resolve JsxOpeningLikeElement as a stateless function element, we will already give its attributes a contextual type
// which is a type of the parameter of the signature we are trying out.
// If there is no contextual type (e.g. we are trying to resolve stateful component), get attributes type from resolving element's tagName
const attributesType = getContextualType(<Expression>attribute.parent);
if (isJsxAttribute(attribute)) {
const attributesType = getApparentTypeOfContextualType(attribute.parent);
if (!attributesType || isTypeAny(attributesType)) {
return undefined;
}
return getTypeOfPropertyOfContextualType(attributesType, attribute.name.escapedText);
}
else {
return attributesType;
return getContextualType(attribute.parent);
}
}
@ -14353,7 +14332,7 @@ namespace ts {
return getContextualTypeForJsxAttribute(<JsxAttribute | JsxSpreadAttribute>parent);
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxSelfClosingElement:
return getAttributesTypeFromJsxOpeningLikeElement(<JsxOpeningLikeElement>parent);
return getContextualJsxElementAttributesType(<JsxOpeningLikeElement>parent);
}
return undefined;
}
@ -14363,6 +14342,145 @@ namespace ts {
return node ? node.contextualMapper : identityMapper;
}
function getContextualJsxElementAttributesType(node: JsxOpeningLikeElement) {
if (isJsxIntrinsicIdentifier(node.tagName)) {
return getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node);
}
const valueType = checkExpression(node.tagName);
if (isTypeAny(valueType)) {
// Short-circuit if the class tag is using an element type 'any'
return anyType;
}
const isJs = isInJavaScriptFile(node);
return mapType(valueType, isJs ? getJsxSignaturesParameterTypesJs : getJsxSignaturesParameterTypes);
}
function getJsxSignaturesParameterTypes(valueType: Type) {
return getJsxSignaturesParameterTypesInternal(valueType, /*isJs*/ false);
}
function getJsxSignaturesParameterTypesJs(valueType: Type) {
return getJsxSignaturesParameterTypesInternal(valueType, /*isJs*/ true);
}
function getJsxSignaturesParameterTypesInternal(valueType: Type, isJs: boolean) {
// If the elemType is a string type, we have to return anyType to prevent an error downstream as we will try to find construct or call signature of the type
if (valueType.flags & TypeFlags.String) {
return anyType;
}
else if (valueType.flags & TypeFlags.StringLiteral) {
// If the elemType is a stringLiteral type, we can then provide a check to make sure that the string literal type is one of the Jsx intrinsic element type
// For example:
// var CustomTag: "h1" = "h1";
// <CustomTag> Hello World </CustomTag>
const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements);
if (intrinsicElementsType !== unknownType) {
const stringLiteralTypeName = (<StringLiteralType>valueType).value;
const intrinsicProp = getPropertyOfType(intrinsicElementsType, escapeLeadingUnderscores(stringLiteralTypeName));
if (intrinsicProp) {
return getTypeOfSymbol(intrinsicProp);
}
const indexSignatureType = getIndexTypeOfType(intrinsicElementsType, IndexKind.String);
if (indexSignatureType) {
return indexSignatureType;
}
}
return anyType;
}
// Resolve the signatures, preferring constructor
let signatures = getSignaturesOfType(valueType, SignatureKind.Construct);
let ctor = true;
if (signatures.length === 0) {
// No construct signatures, try call signatures
signatures = getSignaturesOfType(valueType, SignatureKind.Call);
ctor = false;
if (signatures.length === 0) {
// We found no signatures at all, which is an error
return unknownType;
}
}
return getUnionType(map(signatures, ctor ? isJs ? getJsxPropsTypeFromConstructSignatureJs : getJsxPropsTypeFromConstructSignature : getJsxPropsTypeFromCallSignature), UnionReduction.None);
}
function getJsxPropsTypeFromCallSignature(sig: Signature) {
let propsType = getTypeOfFirstParameterOfSignature(sig);
const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes);
if (intrinsicAttribs !== unknownType) {
propsType = intersectTypes(intrinsicAttribs, propsType);
}
return propsType;
}
function getJsxPropsTypeFromClassType(hostClassType: Type, isJs: boolean) {
if (isTypeAny(hostClassType)) {
return hostClassType;
}
const propsName = getJsxElementPropertiesName();
if (propsName === undefined) {
// There is no type ElementAttributesProperty, return 'any'
return anyType;
}
else if (propsName === "") {
// If there is no e.g. 'props' member in ElementAttributesProperty, use the element class type instead
return hostClassType;
}
else {
const attributesType = getTypeOfPropertyOfType(hostClassType, propsName);
if (!attributesType) {
// There is no property named 'props' on this instance type
return emptyObjectType;
}
else if (isTypeAny(attributesType)) {
// Props is of type 'any' or unknown
return attributesType;
}
else {
// Normal case -- add in IntrinsicClassElements<T> and IntrinsicElements
let apparentAttributesType = attributesType;
const intrinsicClassAttribs = getJsxType(JsxNames.IntrinsicClassAttributes);
if (intrinsicClassAttribs !== unknownType) {
const typeParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol);
apparentAttributesType = intersectTypes(
typeParams
? createTypeReference(<GenericType>intrinsicClassAttribs, fillMissingTypeArguments([hostClassType], typeParams, getMinTypeArgumentCount(typeParams), isJs))
: intrinsicClassAttribs,
apparentAttributesType
);
}
const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes);
if (intrinsicAttribs !== unknownType) {
apparentAttributesType = intersectTypes(intrinsicAttribs, apparentAttributesType);
}
return apparentAttributesType;
}
}
}
function getJsxPropsTypeFromConstructSignatureJs(sig: Signature) {
return getJsxPropsTypeFromConstructSignatureInternal(sig, /*isJs*/ true);
}
function getJsxPropsTypeFromConstructSignature(sig: Signature) {
return getJsxPropsTypeFromConstructSignatureInternal(sig, /*isJs*/ false);
}
function getJsxPropsTypeFromConstructSignatureInternal(sig: Signature, isJs: boolean) {
const hostClassType = getReturnTypeOfSignature(sig);
if (hostClassType) {
return getJsxPropsTypeFromClassType(hostClassType, isJs);
}
return getJsxPropsTypeFromCallSignature(sig);
}
// If the given type is an object or union type with a single signature, and if that signature has at
// least as many parameters as the given function, return the signature. Otherwise return undefined.
function getContextualCallSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature {
@ -14887,7 +15005,7 @@ namespace ts {
let hasSpreadAnyType = false;
let typeToIntersect: Type;
let explicitlySpecifyChildrenAttribute = false;
const jsxChildrenPropertyName = getJsxElementChildrenPropertyname();
const jsxChildrenPropertyName = getJsxElementChildrenPropertyName();
for (const attributeDecl of attributes.properties) {
const member = attributeDecl.symbol;
@ -14988,7 +15106,7 @@ namespace ts {
}
}
else {
childrenTypes.push(checkExpression(child, checkMode));
childrenTypes.push(checkExpressionForMutableLocation(child, checkMode));
}
}
return childrenTypes;
@ -15056,7 +15174,7 @@ namespace ts {
* element is not a class element, or the class element type cannot be determined, returns 'undefined'.
* For example, in the element <MyClass>, the element instance type is `MyClass` (not `typeof MyClass`).
*/
function getJsxElementInstanceType(node: JsxOpeningLikeElement, valueType: Type, sourceAttributesType: Type | undefined) {
function getJsxElementInstanceType(node: JsxOpeningLikeElement, valueType: Type) {
Debug.assert(!(valueType.flags & TypeFlags.Union));
if (isTypeAny(valueType)) {
// Short-circuit if the class tag is using an element type 'any'
@ -15075,27 +15193,21 @@ namespace ts {
}
}
if (sourceAttributesType) {
// Instantiate in context of source type
const instantiatedSignatures = [];
for (const signature of signatures) {
if (signature.typeParameters) {
const isJavascript = isInJavaScriptFile(node);
const inferenceContext = createInferenceContext(signature, /*flags*/ isJavascript ? InferenceFlags.AnyDefault : 0);
const typeArguments = inferJsxTypeArguments(signature, sourceAttributesType, inferenceContext);
instantiatedSignatures.push(getSignatureInstantiation(signature, typeArguments, isJavascript));
}
else {
instantiatedSignatures.push(signature);
}
// Instantiate in context of source type
const instantiatedSignatures = [];
for (const signature of signatures) {
if (signature.typeParameters) {
const isJavascript = isInJavaScriptFile(node);
const inferenceContext = createInferenceContext(signature, /*flags*/ isJavascript ? InferenceFlags.AnyDefault : InferenceFlags.None);
const typeArguments = inferJsxTypeArguments(signature, node, inferenceContext);
instantiatedSignatures.push(getSignatureInstantiation(signature, typeArguments, isJavascript));
}
else {
instantiatedSignatures.push(signature);
}
}
return getUnionType(map(instantiatedSignatures, getReturnTypeOfSignature), UnionReduction.Subtype);
}
else {
// Do not instantiate if no source type is provided - type parameters and their constraints will be used by contextual typing
return getUnionType(map(signatures, getReturnTypeOfSignature), UnionReduction.Subtype);
}
return getUnionType(map(instantiatedSignatures, getReturnTypeOfSignature), UnionReduction.Subtype);
}
/**
@ -15146,7 +15258,7 @@ namespace ts {
return _jsxElementPropertiesName;
}
function getJsxElementChildrenPropertyname(): __String {
function getJsxElementChildrenPropertyName(): __String {
if (!_hasComputedJsxElementChildrenPropertyName) {
_hasComputedJsxElementChildrenPropertyName = true;
_jsxElementChildrenPropertyName = getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer);
@ -15281,14 +15393,13 @@ namespace ts {
*/
function resolveCustomJsxElementAttributesType(openingLikeElement: JsxOpeningLikeElement,
shouldIncludeAllStatelessAttributesType: boolean,
sourceAttributesType: Type | undefined,
elementType: Type,
elementClassType?: Type): Type {
if (elementType.flags & TypeFlags.Union) {
const types = (elementType as UnionType).types;
return getUnionType(types.map(type => {
return resolveCustomJsxElementAttributesType(openingLikeElement, shouldIncludeAllStatelessAttributesType, sourceAttributesType, type, elementClassType);
return resolveCustomJsxElementAttributesType(openingLikeElement, shouldIncludeAllStatelessAttributesType, type, elementClassType);
}), UnionReduction.Subtype);
}
@ -15319,7 +15430,7 @@ namespace ts {
}
// Get the element instance type (the result of newing or invoking this tag)
const elemInstanceType = getJsxElementInstanceType(openingLikeElement, elementType, sourceAttributesType);
const elemInstanceType = getJsxElementInstanceType(openingLikeElement, elementType);
// If we should include all stateless attributes type, then get all attributes type from all stateless function signature.
// Otherwise get only attributes type from the signature picked by choose-overload logic.
@ -15332,58 +15443,11 @@ namespace ts {
}
// Issue an error if this return type isn't assignable to JSX.ElementClass
if (elementClassType && sourceAttributesType) {
if (elementClassType) {
checkTypeRelatedTo(elemInstanceType, elementClassType, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
}
if (isTypeAny(elemInstanceType)) {
return elemInstanceType;
}
const propsName = getJsxElementPropertiesName();
if (propsName === undefined) {
// There is no type ElementAttributesProperty, return 'any'
return anyType;
}
else if (propsName === "") {
// If there is no e.g. 'props' member in ElementAttributesProperty, use the element class type instead
return elemInstanceType;
}
else {
const attributesType = getTypeOfPropertyOfType(elemInstanceType, propsName);
if (!attributesType) {
// There is no property named 'props' on this instance type
return emptyObjectType;
}
else if (isTypeAny(attributesType) || (attributesType === unknownType)) {
// Props is of type 'any' or unknown
return attributesType;
}
else {
// Normal case -- add in IntrinsicClassElements<T> and IntrinsicElements
let apparentAttributesType = attributesType;
const intrinsicClassAttribs = getJsxType(JsxNames.IntrinsicClassAttributes);
if (intrinsicClassAttribs !== unknownType) {
const typeParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol);
if (typeParams) {
if (typeParams.length === 1) {
apparentAttributesType = intersectTypes(createTypeReference(<GenericType>intrinsicClassAttribs, [elemInstanceType]), apparentAttributesType);
}
}
else {
apparentAttributesType = intersectTypes(attributesType, intrinsicClassAttribs);
}
}
const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes);
if (intrinsicAttribs !== unknownType) {
apparentAttributesType = intersectTypes(intrinsicAttribs, apparentAttributesType);
}
return apparentAttributesType;
}
}
return getJsxPropsTypeFromClassType(elemInstanceType, isInJavaScriptFile(openingLikeElement));
}
/**
@ -15415,20 +15479,8 @@ namespace ts {
* @param node a custom JSX opening-like element
* @param shouldIncludeAllStatelessAttributesType a boolean value used by language service to get all possible attributes type from an overload stateless function component
*/
function getCustomJsxElementAttributesType(node: JsxOpeningLikeElement, sourceAttributesType: Type, shouldIncludeAllStatelessAttributesType: boolean): Type {
if (!sourceAttributesType) {
// This ensures we cache non-inference uses of this calculation (ie, contextual types or services)
const links = getNodeLinks(node);
const linkLocation = shouldIncludeAllStatelessAttributesType ? "resolvedJsxElementAllAttributesType" : "resolvedJsxElementAttributesType";
if (!links[linkLocation]) {
const elemClassType = getJsxGlobalElementClassType();
return links[linkLocation] = resolveCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType, sourceAttributesType, checkExpression(node.tagName), elemClassType);
}
return links[linkLocation];
}
else {
return resolveCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType, sourceAttributesType, checkExpression(node.tagName), getJsxGlobalElementClassType());
}
function getCustomJsxElementAttributesType(node: JsxOpeningLikeElement, shouldIncludeAllStatelessAttributesType: boolean): Type {
return resolveCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType, checkExpression(node.tagName), getJsxGlobalElementClassType());
}
/**
@ -15443,7 +15495,7 @@ namespace ts {
else {
// Because in language service, the given JSX opening-like element may be incomplete and therefore,
// we can't resolve to exact signature if the element is a stateless function component so the best thing to do is return all attributes type from all overloads.
return getCustomJsxElementAttributesType(node, /*sourceAttributesType*/ undefined, /*shouldIncludeAllStatelessAttributesType*/ true);
return getCustomJsxElementAttributesType(node, /*shouldIncludeAllStatelessAttributesType*/ true);
}
}
@ -15457,7 +15509,7 @@ namespace ts {
return getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node);
}
else {
return getCustomJsxElementAttributesType(node, /*sourceAttributesType*/ undefined, /*shouldIncludeAllStatelessAttributesType*/ false);
return getCustomJsxElementAttributesType(node, /*shouldIncludeAllStatelessAttributesType*/ false);
}
}
@ -15597,16 +15649,16 @@ namespace ts {
// 3. Check if the two are assignable to each other
// targetAttributesType is a type of an attribute from resolving tagName of an opening-like JSX element.
const targetAttributesType = isJsxIntrinsicIdentifier(openingLikeElement.tagName) ?
getIntrinsicAttributesTypeFromJsxOpeningLikeElement(openingLikeElement) :
getCustomJsxElementAttributesType(openingLikeElement, /*shouldIncludeAllStatelessAttributesType*/ false);
// sourceAttributesType is a type of an attributes properties.
// i.e <div attr1={10} attr2="string" />
// attr1 and attr2 are treated as JSXAttributes attached in the JsxOpeningLikeElement as "attributes".
const sourceAttributesType = createJsxAttributesTypeFromAttributesProperty(openingLikeElement, checkMode);
// targetAttributesType is a type of an attributes from resolving tagName of an opening-like JSX element.
const targetAttributesType = isJsxIntrinsicIdentifier(openingLikeElement.tagName) ?
getIntrinsicAttributesTypeFromJsxOpeningLikeElement(openingLikeElement) :
getCustomJsxElementAttributesType(openingLikeElement, sourceAttributesType, /*shouldIncludeAllStatelessAttributesType*/ false);
// If the targetAttributesType is an emptyObjectType, indicating that there is no property named 'props' on this instance type.
// but there exists a sourceAttributesType, we need to explicitly give an error as normal assignability check allow excess properties and will pass.
if (targetAttributesType === emptyObjectType && (isTypeAny(sourceAttributesType) || getPropertiesOfType(<ResolvedType>sourceAttributesType).length > 0)) {
@ -16482,9 +16534,16 @@ namespace ts {
return getSignatureInstantiation(signature, getInferredTypes(context), isInJavaScriptFile(contextualSignature.declaration));
}
function inferJsxTypeArguments(signature: Signature, sourceAttributesType: Type, context: InferenceContext): Type[] {
function inferJsxTypeArguments(signature: Signature, node: JsxOpeningLikeElement, context: InferenceContext): Type[] {
// Skip context sensitive pass
const skipContextParamType = getTypeAtPosition(signature, 0);
const checkAttrTypeSkipContextSensitive = checkExpressionWithContextualType(node.attributes, skipContextParamType, identityMapper);
inferTypes(context.inferences, checkAttrTypeSkipContextSensitive, skipContextParamType);
// Standard pass
const paramType = getTypeAtPosition(signature, 0);
inferTypes(context.inferences, sourceAttributesType, paramType);
const checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context);
inferTypes(context.inferences, checkAttrType, paramType);
return getInferredTypes(context);
}
@ -17230,7 +17289,7 @@ namespace ts {
let candidate: Signature;
const inferenceContext = originalCandidate.typeParameters ?
createInferenceContext(originalCandidate, /*flags*/ isInJavaScriptFile(node) ? InferenceFlags.AnyDefault : 0) :
createInferenceContext(originalCandidate, /*flags*/ isInJavaScriptFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None) :
undefined;
while (true) {
@ -19216,16 +19275,24 @@ namespace ts {
return stringType;
}
function getContextNode(node: Expression): Node {
if (node.kind === SyntaxKind.JsxAttributes) {
return node.parent.parent; // Needs to be the root JsxElement, so it encompasses the attributes _and_ the children (which are essentially part of the attributes)
}
return node;
}
function checkExpressionWithContextualType(node: Expression, contextualType: Type, contextualMapper: TypeMapper | undefined): Type {
const saveContextualType = node.contextualType;
const saveContextualMapper = node.contextualMapper;
node.contextualType = contextualType;
node.contextualMapper = contextualMapper;
const context = getContextNode(node);
const saveContextualType = context.contextualType;
const saveContextualMapper = context.contextualMapper;
context.contextualType = contextualType;
context.contextualMapper = contextualMapper;
const checkMode = contextualMapper === identityMapper ? CheckMode.SkipContextSensitive :
contextualMapper ? CheckMode.Inferential : CheckMode.Contextual;
const result = checkExpression(node, checkMode);
node.contextualType = saveContextualType;
node.contextualMapper = saveContextualMapper;
context.contextualType = saveContextualType;
context.contextualMapper = saveContextualMapper;
return result;
}

View file

@ -3904,6 +3904,7 @@ namespace ts {
}
export const enum InferenceFlags {
None = 0, // No special inference behaviors
InferUnionTypes = 1 << 0, // Infer union types for disjoint candidates (otherwise unknownType)
NoDefault = 1 << 1, // Infer unknownType for no inferences (otherwise anyType or emptyObjectType)
AnyDefault = 1 << 2, // Infer anyType for no inferences (otherwise emptyObjectType)

View file

@ -2227,6 +2227,7 @@ declare namespace ts {
isFixed: boolean;
}
enum InferenceFlags {
None = 0,
InferUnionTypes = 1,
NoDefault = 2,
AnyDefault = 4,

View file

@ -2227,6 +2227,7 @@ declare namespace ts {
isFixed: boolean;
}
enum InferenceFlags {
None = 0,
InferUnionTypes = 1,
NoDefault = 2,
AnyDefault = 4,

View file

@ -8,12 +8,12 @@ tests/cases/conformance/jsx/file.tsx(31,11): error TS2322: Type '{ children: (El
Type '(Element | ((name: string) => Element))[]' is not assignable to type 'string | Element'.
Type '(Element | ((name: string) => Element))[]' is not assignable to type 'Element'.
Property 'type' is missing in type '(Element | ((name: string) => Element))[]'.
tests/cases/conformance/jsx/file.tsx(37,11): error TS2322: Type '{ children: (Element | 1000000)[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
Type '{ children: (Element | 1000000)[]; a: number; b: string; }' is not assignable to type 'Prop'.
tests/cases/conformance/jsx/file.tsx(37,11): error TS2322: Type '{ children: (number | Element)[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
Type '{ children: (number | Element)[]; a: number; b: string; }' is not assignable to type 'Prop'.
Types of property 'children' are incompatible.
Type '(Element | 1000000)[]' is not assignable to type 'string | Element'.
Type '(Element | 1000000)[]' is not assignable to type 'Element'.
Property 'type' is missing in type '(Element | 1000000)[]'.
Type '(number | Element)[]' is not assignable to type 'string | Element'.
Type '(number | Element)[]' is not assignable to type 'Element'.
Property 'type' is missing in type '(number | Element)[]'.
tests/cases/conformance/jsx/file.tsx(43,11): error TS2322: Type '{ children: (string | Element)[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
Type '{ children: (string | Element)[]; a: number; b: string; }' is not assignable to type 'Prop'.
Types of property 'children' are incompatible.
@ -80,12 +80,12 @@ tests/cases/conformance/jsx/file.tsx(49,11): error TS2322: Type '{ children: Ele
let k3 =
<Comp a={10} b="hi">
~~~~~~~~~~~~~
!!! error TS2322: Type '{ children: (Element | 1000000)[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
!!! error TS2322: Type '{ children: (Element | 1000000)[]; a: number; b: string; }' is not assignable to type 'Prop'.
!!! error TS2322: Type '{ children: (number | Element)[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
!!! error TS2322: Type '{ children: (number | Element)[]; a: number; b: string; }' is not assignable to type 'Prop'.
!!! error TS2322: Types of property 'children' are incompatible.
!!! error TS2322: Type '(Element | 1000000)[]' is not assignable to type 'string | Element'.
!!! error TS2322: Type '(Element | 1000000)[]' is not assignable to type 'Element'.
!!! error TS2322: Property 'type' is missing in type '(Element | 1000000)[]'.
!!! error TS2322: Type '(number | Element)[]' is not assignable to type 'string | Element'.
!!! error TS2322: Type '(number | Element)[]' is not assignable to type 'Element'.
!!! error TS2322: Property 'type' is missing in type '(number | Element)[]'.
<div> My Div </div>
{1000000}
</Comp>;

View file

@ -0,0 +1,27 @@
tests/cases/conformance/jsx/file.tsx(13,27): error TS2322: Type '{ initialValues: { x: string; }; nextValues: (a: { x: string; }) => string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<GenericComponent<{ initialValues: { x: string; }; nextValues: {}; }, { x: string; }>> & { initialValues: { x: string; }; nextValues: {}; } & BaseProps<{ x: string; }> & { children?: ReactNode; }'.
Type '{ initialValues: { x: string; }; nextValues: (a: { x: string; }) => string; }' is not assignable to type 'BaseProps<{ x: string; }>'.
Types of property 'nextValues' are incompatible.
Type '(a: { x: string; }) => string' is not assignable to type '(cur: { x: string; }) => { x: string; }'.
Type 'string' is not assignable to type '{ x: string; }'.
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
import * as React from "react";
interface BaseProps<T> {
initialValues: T;
nextValues: (cur: T) => T;
}
declare class GenericComponent<Props = {}, Values = object> extends React.Component<Props & BaseProps<Values>, {}> {
iv: Values;
}
let a = <GenericComponent initialValues={{ x: "y" }} nextValues={a => a} />; // No error
let b = <GenericComponent initialValues={12} nextValues={a => a} />; // No error - Values should be reinstantiated with `number` (since `object` is a default, not a constraint)
let c = <GenericComponent initialValues={{ x: "y" }} nextValues={a => ({ x: a.x })} />; // No Error
let d = <GenericComponent initialValues={{ x: "y" }} nextValues={a => a.x} />; // Error - `string` is not assignable to `{x: string}`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ initialValues: { x: string; }; nextValues: (a: { x: string; }) => string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<GenericComponent<{ initialValues: { x: string; }; nextValues: {}; }, { x: string; }>> & { initialValues: { x: string; }; nextValues: {}; } & BaseProps<{ x: string; }> & { children?: ReactNode; }'.
!!! error TS2322: Type '{ initialValues: { x: string; }; nextValues: (a: { x: string; }) => string; }' is not assignable to type 'BaseProps<{ x: string; }>'.
!!! error TS2322: Types of property 'nextValues' are incompatible.
!!! error TS2322: Type '(a: { x: string; }) => string' is not assignable to type '(cur: { x: string; }) => { x: string; }'.
!!! error TS2322: Type 'string' is not assignable to type '{ x: string; }'.

View file

@ -0,0 +1,23 @@
//// [file.tsx]
import * as React from "react";
interface BaseProps<T> {
initialValues: T;
nextValues: (cur: T) => T;
}
declare class GenericComponent<Props = {}, Values = object> extends React.Component<Props & BaseProps<Values>, {}> {
iv: Values;
}
let a = <GenericComponent initialValues={{ x: "y" }} nextValues={a => a} />; // No error
let b = <GenericComponent initialValues={12} nextValues={a => a} />; // No error - Values should be reinstantiated with `number` (since `object` is a default, not a constraint)
let c = <GenericComponent initialValues={{ x: "y" }} nextValues={a => ({ x: a.x })} />; // No Error
let d = <GenericComponent initialValues={{ x: "y" }} nextValues={a => a.x} />; // Error - `string` is not assignable to `{x: string}`
//// [file.jsx]
"use strict";
exports.__esModule = true;
var React = require("react");
var a = <GenericComponent initialValues={{ x: "y" }} nextValues={function (a) { return a; }}/>; // No error
var b = <GenericComponent initialValues={12} nextValues={function (a) { return a; }}/>; // No error - Values should be reinstantiated with `number` (since `object` is a default, not a constraint)
var c = <GenericComponent initialValues={{ x: "y" }} nextValues={function (a) { return ({ x: a.x }); }}/>; // No Error
var d = <GenericComponent initialValues={{ x: "y" }} nextValues={function (a) { return a.x; }}/>; // Error - `string` is not assignable to `{x: string}`

View file

@ -0,0 +1,74 @@
=== tests/cases/conformance/jsx/file.tsx ===
import * as React from "react";
>React : Symbol(React, Decl(file.tsx, 0, 6))
interface BaseProps<T> {
>BaseProps : Symbol(BaseProps, Decl(file.tsx, 0, 31))
>T : Symbol(T, Decl(file.tsx, 1, 20))
initialValues: T;
>initialValues : Symbol(BaseProps.initialValues, Decl(file.tsx, 1, 24))
>T : Symbol(T, Decl(file.tsx, 1, 20))
nextValues: (cur: T) => T;
>nextValues : Symbol(BaseProps.nextValues, Decl(file.tsx, 2, 19))
>cur : Symbol(cur, Decl(file.tsx, 3, 15))
>T : Symbol(T, Decl(file.tsx, 1, 20))
>T : Symbol(T, Decl(file.tsx, 1, 20))
}
declare class GenericComponent<Props = {}, Values = object> extends React.Component<Props & BaseProps<Values>, {}> {
>GenericComponent : Symbol(GenericComponent, Decl(file.tsx, 4, 1))
>Props : Symbol(Props, Decl(file.tsx, 5, 31))
>Values : Symbol(Values, Decl(file.tsx, 5, 42))
>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66))
>React : Symbol(React, Decl(file.tsx, 0, 6))
>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66))
>Props : Symbol(Props, Decl(file.tsx, 5, 31))
>BaseProps : Symbol(BaseProps, Decl(file.tsx, 0, 31))
>Values : Symbol(Values, Decl(file.tsx, 5, 42))
iv: Values;
>iv : Symbol(GenericComponent.iv, Decl(file.tsx, 5, 116))
>Values : Symbol(Values, Decl(file.tsx, 5, 42))
}
let a = <GenericComponent initialValues={{ x: "y" }} nextValues={a => a} />; // No error
>a : Symbol(a, Decl(file.tsx, 9, 3))
>GenericComponent : Symbol(GenericComponent, Decl(file.tsx, 4, 1))
>initialValues : Symbol(initialValues, Decl(file.tsx, 9, 25))
>x : Symbol(x, Decl(file.tsx, 9, 42))
>nextValues : Symbol(nextValues, Decl(file.tsx, 9, 52))
>a : Symbol(a, Decl(file.tsx, 9, 65))
>a : Symbol(a, Decl(file.tsx, 9, 65))
let b = <GenericComponent initialValues={12} nextValues={a => a} />; // No error - Values should be reinstantiated with `number` (since `object` is a default, not a constraint)
>b : Symbol(b, Decl(file.tsx, 10, 3))
>GenericComponent : Symbol(GenericComponent, Decl(file.tsx, 4, 1))
>initialValues : Symbol(initialValues, Decl(file.tsx, 10, 25))
>nextValues : Symbol(nextValues, Decl(file.tsx, 10, 44))
>a : Symbol(a, Decl(file.tsx, 10, 57))
>a : Symbol(a, Decl(file.tsx, 10, 57))
let c = <GenericComponent initialValues={{ x: "y" }} nextValues={a => ({ x: a.x })} />; // No Error
>c : Symbol(c, Decl(file.tsx, 11, 3))
>GenericComponent : Symbol(GenericComponent, Decl(file.tsx, 4, 1))
>initialValues : Symbol(initialValues, Decl(file.tsx, 11, 25))
>x : Symbol(x, Decl(file.tsx, 11, 42))
>nextValues : Symbol(nextValues, Decl(file.tsx, 11, 52))
>a : Symbol(a, Decl(file.tsx, 11, 65))
>x : Symbol(x, Decl(file.tsx, 11, 72))
>a.x : Symbol(x, Decl(file.tsx, 11, 42))
>a : Symbol(a, Decl(file.tsx, 11, 65))
>x : Symbol(x, Decl(file.tsx, 11, 42))
let d = <GenericComponent initialValues={{ x: "y" }} nextValues={a => a.x} />; // Error - `string` is not assignable to `{x: string}`
>d : Symbol(d, Decl(file.tsx, 12, 3))
>GenericComponent : Symbol(GenericComponent, Decl(file.tsx, 4, 1))
>initialValues : Symbol(initialValues, Decl(file.tsx, 12, 25))
>x : Symbol(x, Decl(file.tsx, 12, 42))
>nextValues : Symbol(nextValues, Decl(file.tsx, 12, 52))
>a : Symbol(a, Decl(file.tsx, 12, 65))
>a.x : Symbol(x, Decl(file.tsx, 12, 42))
>a : Symbol(a, Decl(file.tsx, 12, 65))
>x : Symbol(x, Decl(file.tsx, 12, 42))

View file

@ -0,0 +1,91 @@
=== tests/cases/conformance/jsx/file.tsx ===
import * as React from "react";
>React : typeof React
interface BaseProps<T> {
>BaseProps : BaseProps<T>
>T : T
initialValues: T;
>initialValues : T
>T : T
nextValues: (cur: T) => T;
>nextValues : (cur: T) => T
>cur : T
>T : T
>T : T
}
declare class GenericComponent<Props = {}, Values = object> extends React.Component<Props & BaseProps<Values>, {}> {
>GenericComponent : GenericComponent<Props, Values>
>Props : Props
>Values : Values
>React.Component : React.Component<Props & BaseProps<Values>, {}>
>React : typeof React
>Component : typeof React.Component
>Props : Props
>BaseProps : BaseProps<T>
>Values : Values
iv: Values;
>iv : Values
>Values : Values
}
let a = <GenericComponent initialValues={{ x: "y" }} nextValues={a => a} />; // No error
>a : JSX.Element
><GenericComponent initialValues={{ x: "y" }} nextValues={a => a} /> : JSX.Element
>GenericComponent : typeof GenericComponent
>initialValues : { x: string; }
>{ x: "y" } : { x: string; }
>x : string
>"y" : "y"
>nextValues : (a: { x: string; }) => { x: string; }
>a => a : (a: { x: string; }) => { x: string; }
>a : { x: string; }
>a : { x: string; }
let b = <GenericComponent initialValues={12} nextValues={a => a} />; // No error - Values should be reinstantiated with `number` (since `object` is a default, not a constraint)
>b : JSX.Element
><GenericComponent initialValues={12} nextValues={a => a} /> : JSX.Element
>GenericComponent : typeof GenericComponent
>initialValues : number
>12 : 12
>nextValues : (a: number) => number
>a => a : (a: number) => number
>a : number
>a : number
let c = <GenericComponent initialValues={{ x: "y" }} nextValues={a => ({ x: a.x })} />; // No Error
>c : JSX.Element
><GenericComponent initialValues={{ x: "y" }} nextValues={a => ({ x: a.x })} /> : JSX.Element
>GenericComponent : typeof GenericComponent
>initialValues : { x: string; }
>{ x: "y" } : { x: string; }
>x : string
>"y" : "y"
>nextValues : (a: { x: string; }) => { x: string; }
>a => ({ x: a.x }) : (a: { x: string; }) => { x: string; }
>a : { x: string; }
>({ x: a.x }) : { x: string; }
>{ x: a.x } : { x: string; }
>x : string
>a.x : string
>a : { x: string; }
>x : string
let d = <GenericComponent initialValues={{ x: "y" }} nextValues={a => a.x} />; // Error - `string` is not assignable to `{x: string}`
>d : JSX.Element
><GenericComponent initialValues={{ x: "y" }} nextValues={a => a.x} /> : JSX.Element
>GenericComponent : typeof GenericComponent
>initialValues : { x: string; }
>{ x: "y" } : { x: string; }
>x : string
>"y" : "y"
>nextValues : (a: { x: string; }) => string
>a => a.x : (a: { x: string; }) => string
>a : { x: string; }
>a.x : string
>a : { x: string; }
>x : string

View file

@ -0,0 +1,68 @@
tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(20,22): error TS2322: Type '{ prop: "x"; children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x">'.
Type '{ prop: "x"; children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; }' is not assignable to type 'LitProps<"x">'.
Types of property 'children' are incompatible.
Type '(p: IntrinsicAttributes & LitProps<"x">) => "y"' is not assignable to type '(x: LitProps<"x">) => "x"'.
Type '"y"' is not assignable to type '"x"'.
tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(21,27): error TS2322: Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x" | "y">'.
Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'LitProps<"x" | "y">'.
Types of property 'children' are incompatible.
Type '(p: IntrinsicAttributes & LitProps<"x">) => "y"' is not assignable to type '(x: LitProps<"x" | "y">) => "x" | "y"'.
Types of parameters 'p' and 'x' are incompatible.
Type 'LitProps<"x" | "y">' is not assignable to type 'IntrinsicAttributes & LitProps<"x">'.
Type 'LitProps<"x" | "y">' is not assignable to type 'LitProps<"x">'.
Types of property 'prop' are incompatible.
Type '"x" | "y"' is not assignable to type '"x"'.
Type '"y"' is not assignable to type '"x"'.
tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(22,29): error TS2322: Type '{ children: () => number; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x">'.
Type '{ children: () => number; prop: "x"; }' is not assignable to type 'LitProps<"x">'.
Types of property 'children' are incompatible.
Type '() => number' is not assignable to type '(x: LitProps<"x">) => "x"'.
Type 'number' is not assignable to type '"x"'.
==== tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx (3 errors) ====
namespace JSX {
export interface Element {}
export interface ElementAttributesProperty { props: {}; }
export interface ElementChildrenAttribute { children: {}; }
export interface IntrinsicAttributes {}
export interface IntrinsicElements { [key: string]: Element }
}
const Elem = <T,U=never>(p: { prop: T, children: (t: T) => T }) => <div></div>;
Elem({prop: {a: "x"}, children: i => ({a: "z"})});
const q = <Elem prop={{a: "x"}} children={i => ({a: "z"})} />
const qq = <Elem prop={{a: "x"}}>{i => ({a: "z"})}</Elem>
interface LitProps<T> { prop: T, children: (x: this) => T }
const ElemLit = <T extends string>(p: LitProps<T>) => <div></div>;
ElemLit({prop: "x", children: () => "x"});
const j = <ElemLit prop="x" children={() => "x"} />
const jj = <ElemLit prop="x">{() => "x"}</ElemLit>
// Should error
const arg = <ElemLit prop="x" children={p => "y"} />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ prop: "x"; children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x">'.
!!! error TS2322: Type '{ prop: "x"; children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; }' is not assignable to type 'LitProps<"x">'.
!!! error TS2322: Types of property 'children' are incompatible.
!!! error TS2322: Type '(p: IntrinsicAttributes & LitProps<"x">) => "y"' is not assignable to type '(x: LitProps<"x">) => "x"'.
!!! error TS2322: Type '"y"' is not assignable to type '"x"'.
const argchild = <ElemLit prop="x">{p => "y"}</ElemLit>
~~~~~~~~
!!! error TS2322: Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x" | "y">'.
!!! error TS2322: Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'LitProps<"x" | "y">'.
!!! error TS2322: Types of property 'children' are incompatible.
!!! error TS2322: Type '(p: IntrinsicAttributes & LitProps<"x">) => "y"' is not assignable to type '(x: LitProps<"x" | "y">) => "x" | "y"'.
!!! error TS2322: Types of parameters 'p' and 'x' are incompatible.
!!! error TS2322: Type 'LitProps<"x" | "y">' is not assignable to type 'IntrinsicAttributes & LitProps<"x">'.
!!! error TS2322: Type 'LitProps<"x" | "y">' is not assignable to type 'LitProps<"x">'.
!!! error TS2322: Types of property 'prop' are incompatible.
!!! error TS2322: Type '"x" | "y"' is not assignable to type '"x"'.
!!! error TS2322: Type '"y"' is not assignable to type '"x"'.
const mismatched = <ElemLit prop="x">{() => 12}</ElemLit>
~~~~~~~~
!!! error TS2322: Type '{ children: () => number; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x">'.
!!! error TS2322: Type '{ children: () => number; prop: "x"; }' is not assignable to type 'LitProps<"x">'.
!!! error TS2322: Types of property 'children' are incompatible.
!!! error TS2322: Type '() => number' is not assignable to type '(x: LitProps<"x">) => "x"'.
!!! error TS2322: Type 'number' is not assignable to type '"x"'.

View file

@ -0,0 +1,38 @@
//// [jsxChildrenGenericContextualTypes.tsx]
namespace JSX {
export interface Element {}
export interface ElementAttributesProperty { props: {}; }
export interface ElementChildrenAttribute { children: {}; }
export interface IntrinsicAttributes {}
export interface IntrinsicElements { [key: string]: Element }
}
const Elem = <T,U=never>(p: { prop: T, children: (t: T) => T }) => <div></div>;
Elem({prop: {a: "x"}, children: i => ({a: "z"})});
const q = <Elem prop={{a: "x"}} children={i => ({a: "z"})} />
const qq = <Elem prop={{a: "x"}}>{i => ({a: "z"})}</Elem>
interface LitProps<T> { prop: T, children: (x: this) => T }
const ElemLit = <T extends string>(p: LitProps<T>) => <div></div>;
ElemLit({prop: "x", children: () => "x"});
const j = <ElemLit prop="x" children={() => "x"} />
const jj = <ElemLit prop="x">{() => "x"}</ElemLit>
// Should error
const arg = <ElemLit prop="x" children={p => "y"} />
const argchild = <ElemLit prop="x">{p => "y"}</ElemLit>
const mismatched = <ElemLit prop="x">{() => 12}</ElemLit>
//// [jsxChildrenGenericContextualTypes.jsx]
"use strict";
var Elem = function (p) { return <div></div>; };
Elem({ prop: { a: "x" }, children: function (i) { return ({ a: "z" }); } });
var q = <Elem prop={{ a: "x" }} children={function (i) { return ({ a: "z" }); }}/>;
var qq = <Elem prop={{ a: "x" }}>{function (i) { return ({ a: "z" }); }}</Elem>;
var ElemLit = function (p) { return <div></div>; };
ElemLit({ prop: "x", children: function () { return "x"; } });
var j = <ElemLit prop="x" children={function () { return "x"; }}/>;
var jj = <ElemLit prop="x">{function () { return "x"; }}</ElemLit>;
// Should error
var arg = <ElemLit prop="x" children={function (p) { return "y"; }}/>;
var argchild = <ElemLit prop="x">{function (p) { return "y"; }}</ElemLit>;
var mismatched = <ElemLit prop="x">{function () { return 12; }}</ElemLit>;

View file

@ -0,0 +1,119 @@
=== tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx ===
namespace JSX {
>JSX : Symbol(JSX, Decl(jsxChildrenGenericContextualTypes.tsx, 0, 0))
export interface Element {}
>Element : Symbol(Element, Decl(jsxChildrenGenericContextualTypes.tsx, 0, 15))
export interface ElementAttributesProperty { props: {}; }
>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(jsxChildrenGenericContextualTypes.tsx, 1, 31))
>props : Symbol(ElementAttributesProperty.props, Decl(jsxChildrenGenericContextualTypes.tsx, 2, 48))
export interface ElementChildrenAttribute { children: {}; }
>ElementChildrenAttribute : Symbol(ElementChildrenAttribute, Decl(jsxChildrenGenericContextualTypes.tsx, 2, 61))
>children : Symbol(ElementChildrenAttribute.children, Decl(jsxChildrenGenericContextualTypes.tsx, 3, 47))
export interface IntrinsicAttributes {}
>IntrinsicAttributes : Symbol(IntrinsicAttributes, Decl(jsxChildrenGenericContextualTypes.tsx, 3, 63))
export interface IntrinsicElements { [key: string]: Element }
>IntrinsicElements : Symbol(IntrinsicElements, Decl(jsxChildrenGenericContextualTypes.tsx, 4, 43))
>key : Symbol(key, Decl(jsxChildrenGenericContextualTypes.tsx, 5, 42))
>Element : Symbol(Element, Decl(jsxChildrenGenericContextualTypes.tsx, 0, 15))
}
const Elem = <T,U=never>(p: { prop: T, children: (t: T) => T }) => <div></div>;
>Elem : Symbol(Elem, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 5))
>T : Symbol(T, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 14))
>U : Symbol(U, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 16))
>p : Symbol(p, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 25))
>prop : Symbol(prop, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 29))
>T : Symbol(T, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 14))
>children : Symbol(children, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 38))
>t : Symbol(t, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 50))
>T : Symbol(T, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 14))
>T : Symbol(T, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 14))
>div : Symbol(JSX.IntrinsicElements, Decl(jsxChildrenGenericContextualTypes.tsx, 4, 43))
>div : Symbol(JSX.IntrinsicElements, Decl(jsxChildrenGenericContextualTypes.tsx, 4, 43))
Elem({prop: {a: "x"}, children: i => ({a: "z"})});
>Elem : Symbol(Elem, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 5))
>prop : Symbol(prop, Decl(jsxChildrenGenericContextualTypes.tsx, 8, 6))
>a : Symbol(a, Decl(jsxChildrenGenericContextualTypes.tsx, 8, 13))
>children : Symbol(children, Decl(jsxChildrenGenericContextualTypes.tsx, 8, 21))
>i : Symbol(i, Decl(jsxChildrenGenericContextualTypes.tsx, 8, 31))
>a : Symbol(a, Decl(jsxChildrenGenericContextualTypes.tsx, 8, 39))
const q = <Elem prop={{a: "x"}} children={i => ({a: "z"})} />
>q : Symbol(q, Decl(jsxChildrenGenericContextualTypes.tsx, 9, 5))
>Elem : Symbol(Elem, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 5))
>prop : Symbol(prop, Decl(jsxChildrenGenericContextualTypes.tsx, 9, 15))
>a : Symbol(a, Decl(jsxChildrenGenericContextualTypes.tsx, 9, 23))
>children : Symbol(children, Decl(jsxChildrenGenericContextualTypes.tsx, 9, 31))
>i : Symbol(i, Decl(jsxChildrenGenericContextualTypes.tsx, 9, 42))
>a : Symbol(a, Decl(jsxChildrenGenericContextualTypes.tsx, 9, 49))
const qq = <Elem prop={{a: "x"}}>{i => ({a: "z"})}</Elem>
>qq : Symbol(qq, Decl(jsxChildrenGenericContextualTypes.tsx, 10, 5))
>Elem : Symbol(Elem, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 5))
>prop : Symbol(prop, Decl(jsxChildrenGenericContextualTypes.tsx, 10, 16))
>a : Symbol(a, Decl(jsxChildrenGenericContextualTypes.tsx, 10, 24))
>i : Symbol(i, Decl(jsxChildrenGenericContextualTypes.tsx, 10, 34))
>a : Symbol(a, Decl(jsxChildrenGenericContextualTypes.tsx, 10, 41))
>Elem : Symbol(Elem, Decl(jsxChildrenGenericContextualTypes.tsx, 7, 5))
interface LitProps<T> { prop: T, children: (x: this) => T }
>LitProps : Symbol(LitProps, Decl(jsxChildrenGenericContextualTypes.tsx, 10, 57))
>T : Symbol(T, Decl(jsxChildrenGenericContextualTypes.tsx, 12, 19))
>prop : Symbol(LitProps.prop, Decl(jsxChildrenGenericContextualTypes.tsx, 12, 23))
>T : Symbol(T, Decl(jsxChildrenGenericContextualTypes.tsx, 12, 19))
>children : Symbol(LitProps.children, Decl(jsxChildrenGenericContextualTypes.tsx, 12, 32))
>x : Symbol(x, Decl(jsxChildrenGenericContextualTypes.tsx, 12, 44))
>T : Symbol(T, Decl(jsxChildrenGenericContextualTypes.tsx, 12, 19))
const ElemLit = <T extends string>(p: LitProps<T>) => <div></div>;
>ElemLit : Symbol(ElemLit, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 5))
>T : Symbol(T, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 17))
>p : Symbol(p, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 35))
>LitProps : Symbol(LitProps, Decl(jsxChildrenGenericContextualTypes.tsx, 10, 57))
>T : Symbol(T, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 17))
>div : Symbol(JSX.IntrinsicElements, Decl(jsxChildrenGenericContextualTypes.tsx, 4, 43))
>div : Symbol(JSX.IntrinsicElements, Decl(jsxChildrenGenericContextualTypes.tsx, 4, 43))
ElemLit({prop: "x", children: () => "x"});
>ElemLit : Symbol(ElemLit, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 5))
>prop : Symbol(prop, Decl(jsxChildrenGenericContextualTypes.tsx, 14, 9))
>children : Symbol(children, Decl(jsxChildrenGenericContextualTypes.tsx, 14, 19))
const j = <ElemLit prop="x" children={() => "x"} />
>j : Symbol(j, Decl(jsxChildrenGenericContextualTypes.tsx, 15, 5))
>ElemLit : Symbol(ElemLit, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 5))
>prop : Symbol(prop, Decl(jsxChildrenGenericContextualTypes.tsx, 15, 18))
>children : Symbol(children, Decl(jsxChildrenGenericContextualTypes.tsx, 15, 27))
const jj = <ElemLit prop="x">{() => "x"}</ElemLit>
>jj : Symbol(jj, Decl(jsxChildrenGenericContextualTypes.tsx, 16, 5))
>ElemLit : Symbol(ElemLit, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 5))
>prop : Symbol(prop, Decl(jsxChildrenGenericContextualTypes.tsx, 16, 19))
>ElemLit : Symbol(ElemLit, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 5))
// Should error
const arg = <ElemLit prop="x" children={p => "y"} />
>arg : Symbol(arg, Decl(jsxChildrenGenericContextualTypes.tsx, 19, 5))
>ElemLit : Symbol(ElemLit, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 5))
>prop : Symbol(prop, Decl(jsxChildrenGenericContextualTypes.tsx, 19, 20))
>children : Symbol(children, Decl(jsxChildrenGenericContextualTypes.tsx, 19, 29))
>p : Symbol(p, Decl(jsxChildrenGenericContextualTypes.tsx, 19, 40))
const argchild = <ElemLit prop="x">{p => "y"}</ElemLit>
>argchild : Symbol(argchild, Decl(jsxChildrenGenericContextualTypes.tsx, 20, 5))
>ElemLit : Symbol(ElemLit, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 5))
>prop : Symbol(prop, Decl(jsxChildrenGenericContextualTypes.tsx, 20, 25))
>p : Symbol(p, Decl(jsxChildrenGenericContextualTypes.tsx, 20, 36))
>ElemLit : Symbol(ElemLit, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 5))
const mismatched = <ElemLit prop="x">{() => 12}</ElemLit>
>mismatched : Symbol(mismatched, Decl(jsxChildrenGenericContextualTypes.tsx, 21, 5))
>ElemLit : Symbol(ElemLit, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 5))
>prop : Symbol(prop, Decl(jsxChildrenGenericContextualTypes.tsx, 21, 27))
>ElemLit : Symbol(ElemLit, Decl(jsxChildrenGenericContextualTypes.tsx, 13, 5))

View file

@ -0,0 +1,165 @@
=== tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx ===
namespace JSX {
>JSX : any
export interface Element {}
>Element : Element
export interface ElementAttributesProperty { props: {}; }
>ElementAttributesProperty : ElementAttributesProperty
>props : {}
export interface ElementChildrenAttribute { children: {}; }
>ElementChildrenAttribute : ElementChildrenAttribute
>children : {}
export interface IntrinsicAttributes {}
>IntrinsicAttributes : IntrinsicAttributes
export interface IntrinsicElements { [key: string]: Element }
>IntrinsicElements : IntrinsicElements
>key : string
>Element : Element
}
const Elem = <T,U=never>(p: { prop: T, children: (t: T) => T }) => <div></div>;
>Elem : <T, U = never>(p: { prop: T; children: (t: T) => T; }) => JSX.Element
><T,U=never>(p: { prop: T, children: (t: T) => T }) => <div></div> : <T, U = never>(p: { prop: T; children: (t: T) => T; }) => JSX.Element
>T : T
>U : U
>p : { prop: T; children: (t: T) => T; }
>prop : T
>T : T
>children : (t: T) => T
>t : T
>T : T
>T : T
><div></div> : JSX.Element
>div : any
>div : any
Elem({prop: {a: "x"}, children: i => ({a: "z"})});
>Elem({prop: {a: "x"}, children: i => ({a: "z"})}) : JSX.Element
>Elem : <T, U = never>(p: { prop: T; children: (t: T) => T; }) => JSX.Element
>{prop: {a: "x"}, children: i => ({a: "z"})} : { prop: { a: string; }; children: (i: { a: string; }) => { a: string; }; }
>prop : { a: string; }
>{a: "x"} : { a: string; }
>a : string
>"x" : "x"
>children : (i: { a: string; }) => { a: string; }
>i => ({a: "z"}) : (i: { a: string; }) => { a: string; }
>i : { a: string; }
>({a: "z"}) : { a: string; }
>{a: "z"} : { a: string; }
>a : string
>"z" : "z"
const q = <Elem prop={{a: "x"}} children={i => ({a: "z"})} />
>q : JSX.Element
><Elem prop={{a: "x"}} children={i => ({a: "z"})} /> : JSX.Element
>Elem : <T, U = never>(p: { prop: T; children: (t: T) => T; }) => JSX.Element
>prop : { a: string; }
>{a: "x"} : { a: string; }
>a : string
>"x" : "x"
>children : (i: { a: string; }) => { a: string; }
>i => ({a: "z"}) : (i: { a: string; }) => { a: string; }
>i : { a: string; }
>({a: "z"}) : { a: string; }
>{a: "z"} : { a: string; }
>a : string
>"z" : "z"
const qq = <Elem prop={{a: "x"}}>{i => ({a: "z"})}</Elem>
>qq : JSX.Element
><Elem prop={{a: "x"}}>{i => ({a: "z"})}</Elem> : JSX.Element
>Elem : <T, U = never>(p: { prop: T; children: (t: T) => T; }) => JSX.Element
>prop : { a: string; }
>{a: "x"} : { a: string; }
>a : string
>"x" : "x"
>i => ({a: "z"}) : (i: { a: string; }) => { a: string; }
>i : { a: string; }
>({a: "z"}) : { a: string; }
>{a: "z"} : { a: string; }
>a : string
>"z" : "z"
>Elem : <T, U = never>(p: { prop: T; children: (t: T) => T; }) => JSX.Element
interface LitProps<T> { prop: T, children: (x: this) => T }
>LitProps : LitProps<T>
>T : T
>prop : T
>T : T
>children : (x: this) => T
>x : this
>T : T
const ElemLit = <T extends string>(p: LitProps<T>) => <div></div>;
>ElemLit : <T extends string>(p: LitProps<T>) => JSX.Element
><T extends string>(p: LitProps<T>) => <div></div> : <T extends string>(p: LitProps<T>) => JSX.Element
>T : T
>p : LitProps<T>
>LitProps : LitProps<T>
>T : T
><div></div> : JSX.Element
>div : any
>div : any
ElemLit({prop: "x", children: () => "x"});
>ElemLit({prop: "x", children: () => "x"}) : JSX.Element
>ElemLit : <T extends string>(p: LitProps<T>) => JSX.Element
>{prop: "x", children: () => "x"} : { prop: "x"; children: () => "x"; }
>prop : "x"
>"x" : "x"
>children : () => "x"
>() => "x" : () => "x"
>"x" : "x"
const j = <ElemLit prop="x" children={() => "x"} />
>j : JSX.Element
><ElemLit prop="x" children={() => "x"} /> : JSX.Element
>ElemLit : <T extends string>(p: LitProps<T>) => JSX.Element
>prop : "x"
>children : () => "x"
>() => "x" : () => "x"
>"x" : "x"
const jj = <ElemLit prop="x">{() => "x"}</ElemLit>
>jj : JSX.Element
><ElemLit prop="x">{() => "x"}</ElemLit> : JSX.Element
>ElemLit : <T extends string>(p: LitProps<T>) => JSX.Element
>prop : "x"
>() => "x" : () => "x"
>"x" : "x"
>ElemLit : <T extends string>(p: LitProps<T>) => JSX.Element
// Should error
const arg = <ElemLit prop="x" children={p => "y"} />
>arg : JSX.Element
><ElemLit prop="x" children={p => "y"} /> : JSX.Element
>ElemLit : <T extends string>(p: LitProps<T>) => JSX.Element
>prop : "x"
>children : (p: JSX.IntrinsicAttributes & LitProps<"x">) => "y"
>p => "y" : (p: JSX.IntrinsicAttributes & LitProps<"x">) => "y"
>p : JSX.IntrinsicAttributes & LitProps<"x">
>"y" : "y"
const argchild = <ElemLit prop="x">{p => "y"}</ElemLit>
>argchild : JSX.Element
><ElemLit prop="x">{p => "y"}</ElemLit> : JSX.Element
>ElemLit : <T extends string>(p: LitProps<T>) => JSX.Element
>prop : "x"
>p => "y" : (p: JSX.IntrinsicAttributes & LitProps<"x">) => "y"
>p : JSX.IntrinsicAttributes & LitProps<"x">
>"y" : "y"
>ElemLit : <T extends string>(p: LitProps<T>) => JSX.Element
const mismatched = <ElemLit prop="x">{() => 12}</ElemLit>
>mismatched : JSX.Element
><ElemLit prop="x">{() => 12}</ElemLit> : JSX.Element
>ElemLit : <T extends string>(p: LitProps<T>) => JSX.Element
>prop : "x"
>() => 12 : () => number
>12 : 12
>ElemLit : <T extends string>(p: LitProps<T>) => JSX.Element

View file

@ -0,0 +1,27 @@
//// [jsxElementClassTooManyParams.tsx]
namespace JSX {
export interface Element {}
export interface IntrinsicClassAttributes<TClass, TOther=never> {
ref?: TClass;
item?: TOther;
}
export interface ElementClass extends Element {}
export interface ElementAttributesProperty { props: {}; }
export interface ElementChildrenAttribute { children: {}; }
export interface IntrinsicAttributes {}
export interface IntrinsicElements { [key: string]: Element }
}
class ElemClass<T extends {x: number}> implements JSX.ElementClass {
constructor(public props: T) {}
}
const elem = <ElemClass x={12} y={24} />
//// [jsxElementClassTooManyParams.jsx]
"use strict";
var ElemClass = /** @class */ (function () {
function ElemClass(props) {
this.props = props;
}
return ElemClass;
}());
var elem = <ElemClass x={12} y={24}/>;

View file

@ -0,0 +1,58 @@
=== tests/cases/compiler/jsxElementClassTooManyParams.tsx ===
namespace JSX {
>JSX : Symbol(JSX, Decl(jsxElementClassTooManyParams.tsx, 0, 0))
export interface Element {}
>Element : Symbol(Element, Decl(jsxElementClassTooManyParams.tsx, 0, 15))
export interface IntrinsicClassAttributes<TClass, TOther=never> {
>IntrinsicClassAttributes : Symbol(IntrinsicClassAttributes, Decl(jsxElementClassTooManyParams.tsx, 1, 31))
>TClass : Symbol(TClass, Decl(jsxElementClassTooManyParams.tsx, 2, 46))
>TOther : Symbol(TOther, Decl(jsxElementClassTooManyParams.tsx, 2, 53))
ref?: TClass;
>ref : Symbol(IntrinsicClassAttributes.ref, Decl(jsxElementClassTooManyParams.tsx, 2, 69))
>TClass : Symbol(TClass, Decl(jsxElementClassTooManyParams.tsx, 2, 46))
item?: TOther;
>item : Symbol(IntrinsicClassAttributes.item, Decl(jsxElementClassTooManyParams.tsx, 3, 21))
>TOther : Symbol(TOther, Decl(jsxElementClassTooManyParams.tsx, 2, 53))
}
export interface ElementClass extends Element {}
>ElementClass : Symbol(ElementClass, Decl(jsxElementClassTooManyParams.tsx, 5, 5))
>Element : Symbol(Element, Decl(jsxElementClassTooManyParams.tsx, 0, 15))
export interface ElementAttributesProperty { props: {}; }
>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(jsxElementClassTooManyParams.tsx, 6, 52))
>props : Symbol(ElementAttributesProperty.props, Decl(jsxElementClassTooManyParams.tsx, 7, 48))
export interface ElementChildrenAttribute { children: {}; }
>ElementChildrenAttribute : Symbol(ElementChildrenAttribute, Decl(jsxElementClassTooManyParams.tsx, 7, 61))
>children : Symbol(ElementChildrenAttribute.children, Decl(jsxElementClassTooManyParams.tsx, 8, 47))
export interface IntrinsicAttributes {}
>IntrinsicAttributes : Symbol(IntrinsicAttributes, Decl(jsxElementClassTooManyParams.tsx, 8, 63))
export interface IntrinsicElements { [key: string]: Element }
>IntrinsicElements : Symbol(IntrinsicElements, Decl(jsxElementClassTooManyParams.tsx, 9, 43))
>key : Symbol(key, Decl(jsxElementClassTooManyParams.tsx, 10, 42))
>Element : Symbol(Element, Decl(jsxElementClassTooManyParams.tsx, 0, 15))
}
class ElemClass<T extends {x: number}> implements JSX.ElementClass {
>ElemClass : Symbol(ElemClass, Decl(jsxElementClassTooManyParams.tsx, 11, 1))
>T : Symbol(T, Decl(jsxElementClassTooManyParams.tsx, 12, 16))
>x : Symbol(x, Decl(jsxElementClassTooManyParams.tsx, 12, 27))
>JSX.ElementClass : Symbol(JSX.ElementClass, Decl(jsxElementClassTooManyParams.tsx, 5, 5))
>JSX : Symbol(JSX, Decl(jsxElementClassTooManyParams.tsx, 0, 0))
>ElementClass : Symbol(JSX.ElementClass, Decl(jsxElementClassTooManyParams.tsx, 5, 5))
constructor(public props: T) {}
>props : Symbol(ElemClass.props, Decl(jsxElementClassTooManyParams.tsx, 13, 16))
>T : Symbol(T, Decl(jsxElementClassTooManyParams.tsx, 12, 16))
}
const elem = <ElemClass x={12} y={24} />
>elem : Symbol(elem, Decl(jsxElementClassTooManyParams.tsx, 15, 5))
>ElemClass : Symbol(ElemClass, Decl(jsxElementClassTooManyParams.tsx, 11, 1))
>x : Symbol(x, Decl(jsxElementClassTooManyParams.tsx, 15, 23))
>y : Symbol(y, Decl(jsxElementClassTooManyParams.tsx, 15, 30))

View file

@ -0,0 +1,61 @@
=== tests/cases/compiler/jsxElementClassTooManyParams.tsx ===
namespace JSX {
>JSX : any
export interface Element {}
>Element : Element
export interface IntrinsicClassAttributes<TClass, TOther=never> {
>IntrinsicClassAttributes : IntrinsicClassAttributes<TClass, TOther>
>TClass : TClass
>TOther : TOther
ref?: TClass;
>ref : TClass | undefined
>TClass : TClass
item?: TOther;
>item : TOther | undefined
>TOther : TOther
}
export interface ElementClass extends Element {}
>ElementClass : ElementClass
>Element : Element
export interface ElementAttributesProperty { props: {}; }
>ElementAttributesProperty : ElementAttributesProperty
>props : {}
export interface ElementChildrenAttribute { children: {}; }
>ElementChildrenAttribute : ElementChildrenAttribute
>children : {}
export interface IntrinsicAttributes {}
>IntrinsicAttributes : IntrinsicAttributes
export interface IntrinsicElements { [key: string]: Element }
>IntrinsicElements : IntrinsicElements
>key : string
>Element : Element
}
class ElemClass<T extends {x: number}> implements JSX.ElementClass {
>ElemClass : ElemClass<T>
>T : T
>x : number
>JSX.ElementClass : any
>JSX : any
>ElementClass : JSX.ElementClass
constructor(public props: T) {}
>props : T
>T : T
}
const elem = <ElemClass x={12} y={24} />
>elem : JSX.Element
><ElemClass x={12} y={24} /> : JSX.Element
>ElemClass : typeof ElemClass
>x : number
>12 : 12
>y : number
>24 : 24

View file

@ -0,0 +1,24 @@
// @strict: true
// @jsx: preserve
namespace JSX {
export interface Element {}
export interface ElementAttributesProperty { props: {}; }
export interface ElementChildrenAttribute { children: {}; }
export interface IntrinsicAttributes {}
export interface IntrinsicElements { [key: string]: Element }
}
const Elem = <T,U=never>(p: { prop: T, children: (t: T) => T }) => <div></div>;
Elem({prop: {a: "x"}, children: i => ({a: "z"})});
const q = <Elem prop={{a: "x"}} children={i => ({a: "z"})} />
const qq = <Elem prop={{a: "x"}}>{i => ({a: "z"})}</Elem>
interface LitProps<T> { prop: T, children: (x: this) => T }
const ElemLit = <T extends string>(p: LitProps<T>) => <div></div>;
ElemLit({prop: "x", children: () => "x"});
const j = <ElemLit prop="x" children={() => "x"} />
const jj = <ElemLit prop="x">{() => "x"}</ElemLit>
// Should error
const arg = <ElemLit prop="x" children={p => "y"} />
const argchild = <ElemLit prop="x">{p => "y"}</ElemLit>
const mismatched = <ElemLit prop="x">{() => 12}</ElemLit>

View file

@ -0,0 +1,18 @@
// @strict: true
// @jsx: preserve
namespace JSX {
export interface Element {}
export interface IntrinsicClassAttributes<TClass, TOther=never> {
ref?: TClass;
item?: TOther;
}
export interface ElementClass extends Element {}
export interface ElementAttributesProperty { props: {}; }
export interface ElementChildrenAttribute { children: {}; }
export interface IntrinsicAttributes {}
export interface IntrinsicElements { [key: string]: Element }
}
class ElemClass<T extends {x: number}> implements JSX.ElementClass {
constructor(public props: T) {}
}
const elem = <ElemClass x={12} y={24} />

View file

@ -0,0 +1,18 @@
// @filename: file.tsx
// @jsx: preserve
// @noLib: true
// @skipLibCheck: true
// @libFiles: react.d.ts,lib.d.ts
import * as React from "react";
interface BaseProps<T> {
initialValues: T;
nextValues: (cur: T) => T;
}
declare class GenericComponent<Props = {}, Values = object> extends React.Component<Props & BaseProps<Values>, {}> {
iv: Values;
}
let a = <GenericComponent initialValues={{ x: "y" }} nextValues={a => a} />; // No error
let b = <GenericComponent initialValues={12} nextValues={a => a} />; // No error - Values should be reinstantiated with `number` (since `object` is a default, not a constraint)
let c = <GenericComponent initialValues={{ x: "y" }} nextValues={a => ({ x: a.x })} />; // No Error
let d = <GenericComponent initialValues={{ x: "y" }} nextValues={a => a.x} />; // Error - `string` is not assignable to `{x: string}`