Merge pull request #13640 from Microsoft/wip-master-statelessOverload

Using overload to figure out function signature for SFC
This commit is contained in:
Yui
2017-02-15 07:17:32 -08:00
committed by GitHub
268 changed files with 11483 additions and 979 deletions
+17
View File
@@ -1364,6 +1364,7 @@ namespace ts {
case SyntaxKind.TypeLiteral:
case SyntaxKind.JSDocTypeLiteral:
case SyntaxKind.JSDocRecordType:
case SyntaxKind.JsxAttributes:
return ContainerFlags.IsContainer;
case SyntaxKind.InterfaceDeclaration:
@@ -1470,6 +1471,7 @@ namespace ts {
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.JSDocRecordType:
case SyntaxKind.JSDocTypeLiteral:
case SyntaxKind.JsxAttributes:
// Interface/Object-types always have their children added to the 'members' of
// their container. They are only accessible through an instance of their
// container, and are never in scope otherwise (even inside the body of the
@@ -1659,6 +1661,14 @@ namespace ts {
return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object");
}
function bindJsxAttributes(node: JsxAttributes) {
return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__jsxAttributes");
}
function bindJsxAttribute(node: JsxAttribute, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
return declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes);
}
function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: string) {
const symbol = createSymbol(symbolFlags, name);
addDeclarationToSymbol(symbol, node, symbolFlags);
@@ -2080,6 +2090,12 @@ namespace ts {
case SyntaxKind.ModuleDeclaration:
return bindModuleDeclaration(<ModuleDeclaration>node);
// Jsx-attributes
case SyntaxKind.JsxAttributes:
return bindJsxAttributes(<JsxAttributes>node);
case SyntaxKind.JsxAttribute:
return bindJsxAttribute(<JsxAttribute>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
// Imports and exports
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.NamespaceImport:
@@ -3156,6 +3172,7 @@ namespace ts {
case SyntaxKind.JsxText:
case SyntaxKind.JsxClosingElement:
case SyntaxKind.JsxAttribute:
case SyntaxKind.JsxAttributes:
case SyntaxKind.JsxSpreadAttribute:
case SyntaxKind.JsxExpression:
// These nodes are Jsx syntax.
+479 -167
View File
@@ -111,7 +111,7 @@ namespace ts {
getExportsOfModule: getExportsOfModuleAsArray,
getExportsAndPropertiesOfModule,
getAmbientModules,
getJsxElementAttributesType,
getAllAttributesTypeFromJsxOpeningLikeElement,
getJsxIntrinsicTagNames,
isOptionalParameter,
tryGetMemberInModuleExports,
@@ -3395,6 +3395,12 @@ namespace ts {
return addOptionality(type, /*optional*/ declaration.questionToken && includeOptionality);
}
if (isJsxAttribute(declaration)) {
// if JSX attribute doesn't have initializer, by default the attribute will have boolean value of true.
// I.e <Elem attr /> is sugar for <Elem attr={true} />
return trueType;
}
// If it is a short-hand property assignment, use the type of the identifier
if (declaration.kind === SyntaxKind.ShorthandPropertyAssignment) {
return checkIdentifier(<Identifier>declaration.name);
@@ -7121,7 +7127,7 @@ namespace ts {
// Returns true if the given expression contains (at any level of nesting) a function or arrow expression
// that is subject to contextual typing.
function isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike): boolean {
function isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike): boolean {
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
switch (node.kind) {
case SyntaxKind.FunctionExpression:
@@ -7144,6 +7150,14 @@ namespace ts {
return isContextSensitiveFunctionLikeDeclaration(<MethodDeclaration>node);
case SyntaxKind.ParenthesizedExpression:
return isContextSensitive((<ParenthesizedExpression>node).expression);
case SyntaxKind.JsxAttributes:
return forEach((<JsxAttributes>node).properties, isContextSensitive);
case SyntaxKind.JsxAttribute:
// If there is no initializer, JSX attribute has a boolean value of true which is not context sensitive.
return (<JsxAttribute>node).initializer && isContextSensitive((<JsxAttribute>node).initializer);
case SyntaxKind.JsxExpression:
// It is possible to that node.expression is undefined (e.g <div x={} />)
return (<JsxExpression>node).expression && isContextSensitive((<JsxExpression>node).expression);
}
return false;
@@ -7836,19 +7850,24 @@ namespace ts {
// is considered known if the object type is empty and the check is for assignability, if the object type has
// index signatures, or if the property is actually declared in the object type. In a union or intersection
// type, a property is considered known if it is known in any constituent type.
function isKnownProperty(type: Type, name: string): boolean {
function isKnownProperty(type: Type, name: string, isComparingJsxAttributes: boolean): boolean {
if (type.flags & TypeFlags.Object) {
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
if ((relation === assignableRelation || relation === comparableRelation) && (type === globalObjectType || isEmptyResolvedType(resolved)) ||
resolved.stringIndexInfo ||
(resolved.numberIndexInfo && isNumericLiteralName(name)) ||
getPropertyOfType(type, name)) {
if ((relation === assignableRelation || relation === comparableRelation) &&
(type === globalObjectType || (!isComparingJsxAttributes && isEmptyObjectType(resolved)))) {
return true;
}
else if (resolved.stringIndexInfo || (resolved.numberIndexInfo && isNumericLiteralName(name))) {
return true;
}
else if (getPropertyOfType(type, name) || (isComparingJsxAttributes && !isUnhyphenatedJsxName(name))) {
// For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known.
return true;
}
}
else if (type.flags & TypeFlags.UnionOrIntersection) {
for (const t of (<UnionOrIntersectionType>type).types) {
if (isKnownProperty(t, name)) {
if (isKnownProperty(t, name, isComparingJsxAttributes)) {
return true;
}
}
@@ -7870,16 +7889,24 @@ namespace ts {
function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean {
if (maybeTypeOfKind(target, TypeFlags.Object) && !(getObjectFlags(target) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) {
const isComparingJsxAttributes = !!(source.flags & TypeFlags.JsxAttributes);
for (const prop of getPropertiesOfObjectType(source)) {
if (!isKnownProperty(target, prop.name)) {
if (!isKnownProperty(target, prop.name, isComparingJsxAttributes)) {
if (reportErrors) {
// We know *exactly* where things went wrong when comparing the types.
// Use this property as the error node as this will be more helpful in
// reasoning about what went wrong.
Debug.assert(!!errorNode);
errorNode = prop.valueDeclaration;
reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1,
symbolToString(prop), typeToString(target));
if (isJsxAttributes(errorNode)) {
// JsxAttributes has an object-literal flag and undergo same type-assignablity check as normal object-literal.
// However, using an object-literal error message will be very confusing to the users so we give different a message.
reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(prop), typeToString(target));
}
else {
errorNode = prop.valueDeclaration;
reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1,
symbolToString(prop), typeToString(target));
}
}
return true;
}
@@ -11627,21 +11654,20 @@ namespace ts {
}
function getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute) {
const kind = attribute.kind;
const jsxElement = attribute.parent as JsxOpeningLikeElement;
const attrsType = getJsxElementAttributesType(jsxElement);
// 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 (attribute.kind === SyntaxKind.JsxAttribute) {
if (!attrsType || isTypeAny(attrsType)) {
if (isJsxAttribute(attribute)) {
if (!attributesType || isTypeAny(attributesType)) {
return undefined;
}
return getTypeOfPropertyOfType(attrsType, (attribute as JsxAttribute).name.text);
return getTypeOfPropertyOfType(attributesType, (attribute as JsxAttribute).name.text);
}
else if (attribute.kind === SyntaxKind.JsxSpreadAttribute) {
return attrsType;
else {
return attributesType;
}
Debug.fail(`Expected JsxAttribute or JsxSpreadAttribute, got ts.SyntaxKind[${kind}]`);
}
// Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily
@@ -11714,6 +11740,9 @@ namespace ts {
case SyntaxKind.JsxAttribute:
case SyntaxKind.JsxSpreadAttribute:
return getContextualTypeForJsxAttribute(<JsxAttribute | JsxSpreadAttribute>parent);
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxSelfClosingElement:
return getAttributesTypeFromJsxOpeningLikeElement(<JsxOpeningLikeElement>parent);
}
return undefined;
}
@@ -12210,70 +12239,95 @@ namespace ts {
}
}
function checkJsxAttribute(node: JsxAttribute, elementAttributesType: Type, nameTable: Map<boolean>) {
let correspondingPropType: Type = undefined;
/**
* Get attributes type of the JSX opening-like element. The result is from resolving "attributes" property of the opening-like element.
*
* @param openingLikeElement a JSX opening-like element
* @param filter a function to remove attributes that will not participate in checking whether attributes are assignable
* @return an anonymous type (similar to the one returned by checkObjectLiteral) in which its properties are attributes property.
*/
function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, filter?: (symbol: Symbol) => boolean, contextualMapper?: TypeMapper) {
const attributes = openingLikeElement.attributes;
let attributesTable = createMap<Symbol>();
let spread: Type = emptyObjectType;
let attributesArray: Symbol[] = [];
for (const attributeDecl of attributes.properties) {
const member = attributeDecl.symbol;
if (isJsxAttribute(attributeDecl)) {
const exprType = attributeDecl.initializer ?
checkExpression(attributeDecl.initializer, contextualMapper) :
trueType; // <Elem attr /> is sugar for <Elem attr={true} />
// We need to unconditionally get the expression type
let exprType: Type;
if (node.initializer) {
exprType = checkExpression(node.initializer);
}
else {
// <Elem attr /> is sugar for <Elem attr={true} />
exprType = booleanType;
}
// Look up the corresponding property for this attribute
if (elementAttributesType === emptyObjectType && isUnhyphenatedJsxName(node.name.text)) {
// If there is no 'props' property, you may not have non-"data-" attributes
error(node.parent, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, getJsxElementPropertiesName());
}
else if (elementAttributesType && !isTypeAny(elementAttributesType)) {
const correspondingPropSymbol = getPropertyOfType(elementAttributesType, node.name.text);
correspondingPropType = correspondingPropSymbol && getTypeOfSymbol(correspondingPropSymbol);
if (isUnhyphenatedJsxName(node.name.text)) {
const attributeType = getTypeOfPropertyOfType(elementAttributesType, getTextOfPropertyName(node.name)) || getIndexTypeOfType(elementAttributesType, IndexKind.String);
if (attributeType) {
correspondingPropType = attributeType;
const attributeSymbol = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name);
attributeSymbol.declarations = member.declarations;
attributeSymbol.parent = member.parent;
if (member.valueDeclaration) {
attributeSymbol.valueDeclaration = member.valueDeclaration;
}
else {
// If there's no corresponding property with this name, error
if (!correspondingPropType) {
error(node.name, Diagnostics.Property_0_does_not_exist_on_type_1, node.name.text, typeToString(elementAttributesType));
return unknownType;
}
attributeSymbol.type = exprType;
attributeSymbol.target = member;
attributesTable.set(attributeSymbol.name, attributeSymbol);
attributesArray.push(attributeSymbol);
}
else {
Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute);
if (attributesArray.length > 0) {
spread = getSpreadType(spread, createJsxAttributesType(attributes.symbol, attributesTable));
attributesArray = [];
attributesTable = createMap<Symbol>();
}
const exprType = checkExpression(attributeDecl.expression);
if (!(exprType.flags & (TypeFlags.Object | TypeFlags.Any))) {
error(attributeDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types);
return anyType;
}
if (isTypeAny(exprType)) {
return anyType;
}
spread = getSpreadType(spread, exprType);
}
}
if (correspondingPropType) {
checkTypeAssignableTo(exprType, correspondingPropType, node);
if (spread !== emptyObjectType) {
if (attributesArray.length > 0) {
spread = getSpreadType(spread, createJsxAttributesType(attributes.symbol, attributesTable));
attributesArray = [];
attributesTable = createMap<Symbol>();
}
attributesArray = getPropertiesOfType(spread);
}
nameTable.set(node.name.text, true);
return exprType;
attributesTable = createMap<Symbol>();
if (attributesArray) {
forEach(attributesArray, (attr) => {
if (!filter || filter(attr)) {
attributesTable.set(attr.name, attr);
}
});
}
return createJsxAttributesType(attributes.symbol, attributesTable);
/**
* Create anonymous type from given attributes symbol table.
* @param symbol a symbol of JsxAttributes containing attributes corresponding to attributesTable
* @param attributesTable a symbol table of attributes property
*/
function createJsxAttributesType(symbol: Symbol, attributesTable: Map<Symbol>) {
const result = createAnonymousType(symbol, attributesTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral;
result.flags |= TypeFlags.JsxAttributes | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag;
result.objectFlags |= ObjectFlags.ObjectLiteral;
return result;
}
}
function checkJsxSpreadAttribute(node: JsxSpreadAttribute, elementAttributesType: Type, nameTable: Map<boolean>) {
if (compilerOptions.jsx === JsxEmit.React) {
checkExternalEmitHelpers(node, ExternalEmitHelpers.Assign);
}
const type = checkExpression(node.expression);
const props = getPropertiesOfType(type);
for (const prop of props) {
// Is there a corresponding property in the element attributes type? Skip checking of properties
// that have already been assigned to, as these are not actually pushed into the resulting type
if (!nameTable.get(prop.name)) {
const targetPropSym = getPropertyOfType(elementAttributesType, prop.name);
if (targetPropSym) {
const msg = chainDiagnosticMessages(undefined, Diagnostics.Property_0_of_JSX_spread_attribute_is_not_assignable_to_target_property, prop.name);
checkTypeAssignableTo(getTypeOfSymbol(prop), getTypeOfSymbol(targetPropSym), node, undefined, msg);
}
nameTable.set(prop.name, true);
}
}
return type;
/**
* Check attributes property of opening-like element. This function is called during chooseOverload to get call signature of a JSX opening-like element.
* (See "checkApplicableSignatureForJsxOpeningLikeElement" for how the function is used)
* @param node a JSXAttributes to be resolved of its type
*/
function checkJsxAttributes(node: JsxAttributes, contextualMapper?: TypeMapper) {
return createJsxAttributesTypeFromAttributesProperty(node.parent as JsxOpeningLikeElement, /*filter*/ undefined, contextualMapper);
}
function getJsxType(name: string) {
@@ -12388,29 +12442,137 @@ namespace ts {
}
/**
* Given React element instance type and the class type, resolve the Jsx type
* Pass elemType to handle individual type in the union typed element type.
* Get JSX attributes type by trying to resolve openingLikeElement as a stateless function component.
* Return only attributes type of successfully resolved call signature.
* This function assumes that the caller handled other possible element type of the JSX element (e.g. stateful component)
* Unlike tryGetAllJsxStatelessFunctionAttributesType, this function is a default behavior of type-checkers.
* @param openingLikeElement a JSX opening-like element to find attributes type
* @param elementType a type of the opening-like element. This elementType can't be an union type
* @param elemInstanceType an element instance type (the result of newing or invoking this tag)
* @param elementClassType a JSX-ElementClass type. This is a result of looking up ElementClass interface in the JSX global
*/
function getResolvedJsxType(node: JsxOpeningLikeElement, elemType?: Type, elemClassType?: Type): Type {
if (!elemType) {
elemType = checkExpression(node.tagName);
function defaultTryGetJsxStatelessFunctionAttributesType(openingLikeElement: JsxOpeningLikeElement, elementType: Type, elemInstanceType: Type, elementClassType?: Type): Type {
Debug.assert(!(elementType.flags & TypeFlags.Union));
if (!elementClassType || !isTypeAssignableTo(elemInstanceType, elementClassType)) {
if (jsxElementType) {
// We don't call getResolvedSignature here because we have already resolve the type of JSX Element.
const callSignature = getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, /*candidatesOutArray*/ undefined);
if (callSignature !== unknownSignature) {
const callReturnType = callSignature && getReturnTypeOfSignature(callSignature);
let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0]));
if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) {
// Intersect in JSX.IntrinsicAttributes if it exists
const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes);
if (intrinsicAttributes !== unknownType) {
paramType = intersectTypes(intrinsicAttributes, paramType);
}
return paramType;
}
}
}
}
if (elemType.flags & TypeFlags.Union) {
const types = (<UnionOrIntersectionType>elemType).types;
return getUnionType(map(types, type => {
return getResolvedJsxType(node, type, elemClassType);
return undefined;
}
/**
* Get JSX attributes type by trying to resolve openingLikeElement as a stateless function component.
* Return all attributes type of resolved call signature including candidate signatures.
* This function assumes that the caller handled other possible element type of the JSX element.
* This function is a behavior used by language service when looking up completion in JSX element.
* @param openingLikeElement a JSX opening-like element to find attributes type
* @param elementType a type of the opening-like element. This elementType can't be an union type
* @param elemInstanceType an element instance type (the result of newing or invoking this tag)
* @param elementClassType a JSX-ElementClass type. This is a result of looking up ElementClass interface in the JSX global
*/
function tryGetAllJsxStatelessFunctionAttributesType(openingLikeElement: JsxOpeningLikeElement, elementType: Type, elemInstanceType: Type, elementClassType?: Type): Type {
Debug.assert(!(elementType.flags & TypeFlags.Union));
if (!elementClassType || !isTypeAssignableTo(elemInstanceType, elementClassType)) {
// Is this is a stateless function component? See if its single signature's return type is assignable to the JSX Element Type
if (jsxElementType) {
// We don't call getResolvedSignature because here we have already resolve the type of JSX Element.
const candidatesOutArray: Signature[] = [];
getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, candidatesOutArray);
let result: Type;
let allMatchingAttributesType: Type;
for (const candidate of candidatesOutArray) {
const callReturnType = getReturnTypeOfSignature(candidate);
const paramType = callReturnType && (candidate.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(candidate.parameters[0]));
if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) {
let shouldBeCandidate = true;
for (const attribute of openingLikeElement.attributes.properties) {
if (isJsxAttribute(attribute) &&
isUnhyphenatedJsxName(attribute.name.text) &&
!getPropertyOfType(paramType, attribute.name.text)) {
shouldBeCandidate = false;
break;
}
}
if (shouldBeCandidate) {
result = intersectTypes(result, paramType);
}
allMatchingAttributesType = intersectTypes(allMatchingAttributesType, paramType);
}
}
// If we can't find any matching, just return everything.
if (!result) {
result = allMatchingAttributesType;
}
// Intersect in JSX.IntrinsicAttributes if it exists
const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes);
if (intrinsicAttributes !== unknownType) {
result = intersectTypes(intrinsicAttributes, result);
}
return result;
}
}
return undefined;
}
/**
* Resolve attributes type of the given opening-like element. The attributes type is a type of attributes associated with the given elementType.
* For instance:
* declare function Foo(attr: { p1: string}): JSX.Element;
* <Foo p1={10} />; // This function will try resolve "Foo" and return an attributes type of "Foo" which is "{ p1: string }"
*
* The function is intended to initially be called from getAttributesTypeFromJsxOpeningLikeElement which already handle JSX-intrinsic-element..
* This function will try to resolve custom JSX attributes type in following order: string literal, stateless function, and stateful component
*
* @param openingLikeElement a non-intrinsic JSXOPeningLikeElement
* @param shouldIncludeAllStatelessAttributesType a boolean indicating whether to include all attributes types from all stateless function signature
* @param elementType an instance type of the given opening-like element. If undefined, the function will check type openinglikeElement's tagname.
* @param elementClassType a JSX-ElementClass type. This is a result of looking up ElementClass interface in the JSX global (imported from react.d.ts)
* @return attributes type if able to resolve the type of node
* anyType if there is no type ElementAttributesProperty or there is an error
* emptyObjectType if there is no "prop" in the element instance type
**/
function resolveCustomJsxElementAttributesType(openingLikeElement: JsxOpeningLikeElement,
shouldIncludeAllStatelessAttributesType: boolean,
elementType?: Type,
elementClassType?: Type): Type {
if (!elementType) {
elementType = checkExpression(openingLikeElement.tagName);
}
if (elementType.flags & TypeFlags.Union) {
const types = (elementType as UnionType).types;
return getUnionType(types.map(type => {
return resolveCustomJsxElementAttributesType(openingLikeElement, shouldIncludeAllStatelessAttributesType, type, elementClassType);
}), /*subtypeReduction*/ true);
}
// 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 (elemType.flags & TypeFlags.String) {
if (elementType.flags & TypeFlags.String) {
return anyType;
}
else if (elemType.flags & TypeFlags.StringLiteral) {
else if (elementType.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 = (<LiteralType>elemType).text;
const stringLiteralTypeName = (<LiteralType>elementType).text;
const intrinsicProp = getPropertyOfType(intrinsicElementsType, stringLiteralTypeName);
if (intrinsicProp) {
return getTypeOfSymbol(intrinsicProp);
@@ -12419,37 +12581,28 @@ namespace ts {
if (indexSignatureType) {
return indexSignatureType;
}
error(node, Diagnostics.Property_0_does_not_exist_on_type_1, stringLiteralTypeName, "JSX." + JsxNames.IntrinsicElements);
error(openingLikeElement, Diagnostics.Property_0_does_not_exist_on_type_1, stringLiteralTypeName, "JSX." + JsxNames.IntrinsicElements);
}
// If we need to report an error, we already done so here. So just return any to prevent any more error downstream
return anyType;
}
// Get the element instance type (the result of newing or invoking this tag)
const elemInstanceType = getJsxElementInstanceType(node, elemType);
const elemInstanceType = getJsxElementInstanceType(openingLikeElement, elementType);
if (!elemClassType || !isTypeAssignableTo(elemInstanceType, elemClassType)) {
// Is this is a stateless function component? See if its single signature's return type is
// assignable to the JSX Element Type
if (jsxElementType) {
const callSignatures = elemType && getSignaturesOfType(elemType, SignatureKind.Call);
const callSignature = callSignatures && callSignatures.length > 0 && callSignatures[0];
const callReturnType = callSignature && getReturnTypeOfSignature(callSignature);
let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0]));
if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) {
// Intersect in JSX.IntrinsicAttributes if it exists
const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes);
if (intrinsicAttributes !== unknownType) {
paramType = intersectTypes(intrinsicAttributes, paramType);
}
return paramType;
}
}
// 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.
const statelessAttributesType = shouldIncludeAllStatelessAttributesType ?
tryGetAllJsxStatelessFunctionAttributesType(openingLikeElement, elementType, elemInstanceType, elementClassType) :
defaultTryGetJsxStatelessFunctionAttributesType(openingLikeElement, elementType, elemInstanceType, elementClassType);
if (statelessAttributesType) {
return statelessAttributesType;
}
// Issue an error if this return type isn't assignable to JSX.ElementClass
if (elemClassType) {
checkTypeRelatedTo(elemInstanceType, elemClassType, assignableRelation, node, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
if (elementClassType) {
checkTypeRelatedTo(elemInstanceType, elementClassType, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
}
if (isTypeAny(elemInstanceType)) {
@@ -12478,7 +12631,7 @@ namespace ts {
}
else if (attributesType.flags & TypeFlags.Union) {
// Props cannot be a union type
error(node.tagName, Diagnostics.JSX_element_attributes_type_0_may_not_be_a_union_type, typeToString(attributesType));
error(openingLikeElement.tagName, Diagnostics.JSX_element_attributes_type_0_may_not_be_a_union_type, typeToString(attributesType));
return anyType;
}
else {
@@ -12508,30 +12661,71 @@ namespace ts {
}
/**
* Given an opening/self-closing element, get the 'element attributes type', i.e. the type that tells
* us which attributes are valid on a given element.
* Get attributes type of the given intrinsic opening-like Jsx element by resolving the tag name.
* The function is intended to be called from a function which has checked that the opening element is an intrinsic element.
* @param node an intrinsic JSX opening-like element
*/
function getJsxElementAttributesType(node: JsxOpeningLikeElement): Type {
function getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node: JsxOpeningLikeElement): Type {
Debug.assert(isJsxIntrinsicIdentifier(node.tagName));
const links = getNodeLinks(node);
if (!links.resolvedJsxType) {
if (isJsxIntrinsicIdentifier(node.tagName)) {
const symbol = getIntrinsicTagSymbol(node);
if (links.jsxFlags & JsxFlags.IntrinsicNamedElement) {
return links.resolvedJsxType = getTypeOfSymbol(symbol);
}
else if (links.jsxFlags & JsxFlags.IntrinsicIndexedElement) {
return links.resolvedJsxType = getIndexInfoOfSymbol(symbol, IndexKind.String).type;
}
else {
return links.resolvedJsxType = unknownType;
}
if (!links.resolvedJsxElementAttributesType) {
const symbol = getIntrinsicTagSymbol(node);
if (links.jsxFlags & JsxFlags.IntrinsicNamedElement) {
return links.resolvedJsxElementAttributesType = getTypeOfSymbol(symbol);
}
else if (links.jsxFlags & JsxFlags.IntrinsicIndexedElement) {
return links.resolvedJsxElementAttributesType = getIndexInfoOfSymbol(symbol, IndexKind.String).type;
}
else {
const elemClassType = getJsxGlobalElementClassType();
return links.resolvedJsxType = getResolvedJsxType(node, undefined, elemClassType);
return links.resolvedJsxElementAttributesType = unknownType;
}
}
return links.resolvedJsxType;
return links.resolvedJsxElementAttributesType;
}
/**
* Get attributes type of the given custom opening-like JSX element.
* This function is intended to be called from a caller that handles intrinsic JSX element already.
* @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, shouldIncludeAllStatelessAttributesType: boolean): Type {
const links = getNodeLinks(node);
if (!links.resolvedJsxElementAttributesType) {
const elemClassType = getJsxGlobalElementClassType();
return links.resolvedJsxElementAttributesType = resolveCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType, undefined, elemClassType);
}
return links.resolvedJsxElementAttributesType;
}
/**
* Get all possible attributes type, especially from an overload stateless function component, of the given JSX opening-like element.
* This function is called by language service (see: completions-tryGetGlobalSymbols).
* @param node a JSX opening-like element to get attributes type for
*/
function getAllAttributesTypeFromJsxOpeningLikeElement(node: JsxOpeningLikeElement): Type {
if (isJsxIntrinsicIdentifier(node.tagName)) {
return getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node);
}
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, /*shouldIncludeAllStatelessAttributesType*/ true);
}
}
/**
* Get the attributes type, which indicates the attributes that are valid on the given JSXOpeningLikeElement.
* @param node a JSXOpeningLikeElement node
* @return an attributes type of the given node
*/
function getAttributesTypeFromJsxOpeningLikeElement(node: JsxOpeningLikeElement): Type {
if (isJsxIntrinsicIdentifier(node.tagName)) {
return getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node);
}
else {
return getCustomJsxElementAttributesType(node, /*shouldIncludeAllStatelessAttributesType*/ false);
}
}
/**
@@ -12540,7 +12734,7 @@ namespace ts {
* that have no matching element attributes type property.
*/
function getJsxAttributePropertySymbol(attrib: JsxAttribute): Symbol {
const attributesType = getJsxElementAttributesType(<JsxOpeningElement>attrib.parent);
const attributesType = getAttributesTypeFromJsxOpeningLikeElement(attrib.parent.parent as JsxOpeningElement);
const prop = getPropertyOfType(attributesType, attrib.name.text);
return prop || unknownSymbol;
}
@@ -12552,7 +12746,9 @@ namespace ts {
return jsxElementClassType;
}
/// Returns all the properties of the Jsx.IntrinsicElements interface
/**
* Returns all the properties of the Jsx.IntrinsicElements interface
*/
function getJsxIntrinsicTagNames(): Symbol[] {
const intrinsics = getJsxType(JsxNames.IntrinsicElements);
return intrinsics ? getPropertiesOfType(intrinsics) : emptyArray;
@@ -12590,41 +12786,48 @@ namespace ts {
}
}
const targetAttributesType = getJsxElementAttributesType(node);
checkJsxAttributesAssignableToTagNameAttributes(node);
}
const nameTable = createMap<boolean>();
// Process this array in right-to-left order so we know which
// attributes (mostly from spreads) are being overwritten and
// thus should have their types ignored
let sawSpreadedAny = false;
for (let i = node.attributes.length - 1; i >= 0; i--) {
if (node.attributes[i].kind === SyntaxKind.JsxAttribute) {
checkJsxAttribute(<JsxAttribute>(node.attributes[i]), targetAttributesType, nameTable);
}
else {
Debug.assert(node.attributes[i].kind === SyntaxKind.JsxSpreadAttribute);
const spreadType = checkJsxSpreadAttribute(<JsxSpreadAttribute>(node.attributes[i]), targetAttributesType, nameTable);
if (isTypeAny(spreadType)) {
sawSpreadedAny = true;
}
}
/**
* Check whether the given attributes of JSX opening-like element is assignable to the tagName attributes.
* Get the attributes type of the opening-like element through resolving the tagName, "target attributes"
* Check assignablity between given attributes property, "source attributes", and the "target attributes"
* @param openingLikeElement an opening-like JSX element to check its JSXAttributes
*/
function checkJsxAttributesAssignableToTagNameAttributes(openingLikeElement: JsxOpeningLikeElement) {
// The function involves following steps:
// 1. Figure out expected attributes type by resolving tagName of the JSX opening-like element, targetAttributesType.
// During these steps, we will try to resolve the tagName as intrinsic name, stateless function, stateful component (in the order)
// 2. Solved JSX attributes type given by users, sourceAttributesType, which is by resolving "attributes" property of the JSX opening-like element.
// 3. Check if the two are assignable to each other
// 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, /*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,
attribute => {
return isUnhyphenatedJsxName(attribute.name) || !!(getPropertyOfType(targetAttributesType, attribute.name));
});
// 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) || (<ResolvedType>sourceAttributesType).properties.length > 0)) {
error(openingLikeElement, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, getJsxElementPropertiesName());
}
// Check that all required properties have been provided. If an 'any'
// was spreaded in, though, assume that it provided all required properties
if (targetAttributesType && !sawSpreadedAny) {
const targetProperties = getPropertiesOfType(targetAttributesType);
for (const targetProperty of targetProperties) {
if (!(targetProperty.flags & SymbolFlags.Optional) && !nameTable.get(targetProperty.name)) {
error(node, Diagnostics.Property_0_is_missing_in_type_1, targetProperty.name, typeToString(targetAttributesType));
}
}
else {
checkTypeAssignableTo(sourceAttributesType, targetAttributesType, openingLikeElement.attributes.properties.length > 0 ? openingLikeElement.attributes : openingLikeElement);
}
}
function checkJsxExpression(node: JsxExpression) {
function checkJsxExpression(node: JsxExpression, contextualMapper?: TypeMapper) {
if (node.expression) {
const type = checkExpression(node.expression);
const type = checkExpression(node.expression, contextualMapper);
if (node.dotDotDotToken && type !== anyType && !isArrayType(type)) {
error(node, Diagnostics.JSX_spread_child_must_be_an_array_type, node.toString(), typeToString(type));
}
@@ -13110,6 +13313,11 @@ namespace ts {
let isDecorator: boolean;
let spreadArgIndex = -1;
if (isJsxOpeningLikeElement(node)) {
// The arity check will be done in "checkApplicableSignatureForJsxOpeningLikeElement".
return true;
}
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
const tagExpression = <TaggedTemplateExpression>node;
@@ -13151,7 +13359,7 @@ namespace ts {
argCount = signatureHelpTrailingComma ? args.length + 1 : args.length;
// If we are missing the close paren, the call is incomplete.
// If we are missing the close parenthesis, the call is incomplete.
callIsIncomplete = callExpression.arguments.end === callExpression.end;
typeArguments = callExpression.typeArguments;
@@ -13311,7 +13519,44 @@ namespace ts {
return typeArgumentsAreAssignable;
}
/**
* Check if the given signature can possibly be a signature called by the JSX opening-like element.
* @param node a JSX opening-like element we are trying to figure its call signature
* @param signature a candidate signature we are trying whether it is a call signature
* @param relation a relationship to check parameter and argument type
* @param excludeArgument
*/
function checkApplicableSignatureForJsxOpeningLikeElement(node: JsxOpeningLikeElement, signature: Signature, relation: Map<RelationComparisonResult>) {
// JSX opening-like element has correct arity for stateless-function component if the one of the following condition is true:
// 1. callIsIncomplete
// 2. attributes property has same number of properties as the parameter object type.
// We can figure that out by resolving attributes property and check number of properties in the resolved type
// If the call has correct arity, we will then check if the argument type and parameter type is assignable
const callIsIncomplete = node.attributes.end === node.end; // If we are missing the close "/>", the call is incomplete
if (callIsIncomplete) {
return true;
}
const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1;
// Stateless function components can have maximum of three arguments: "props", "context", and "updater".
// However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props,
// can be specified by users through attributes property.
const paramType = getTypeAtPosition(signature, 0);
const attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined);
const argProperties = getPropertiesOfType(attributesType);
for (const arg of argProperties) {
if (!getPropertyOfType(paramType, arg.name) && isUnhyphenatedJsxName(arg.name)) {
return false;
}
}
return checkTypeRelatedTo(attributesType, paramType, relation, /*errorNode*/ undefined, headMessage);
}
function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map<RelationComparisonResult>, excludeArgument: boolean[], reportErrors: boolean) {
if (isJsxOpeningLikeElement(node)) {
return checkApplicableSignatureForJsxOpeningLikeElement(<JsxOpeningLikeElement>node, signature, relation);
}
const thisType = getThisTypeOfSignature(signature);
if (thisType && thisType !== voidType && node.kind !== SyntaxKind.NewExpression) {
// If the called expression is not of the form `x.f` or `x["f"]`, then sourceType = voidType
@@ -13393,8 +13638,11 @@ namespace ts {
// `getEffectiveArgumentCount` and `getEffectiveArgumentType` below.
return undefined;
}
else if (isJsxOpeningLikeElement(node)) {
args = node.attributes.properties.length > 0 ? [node.attributes] : emptyArray;
}
else {
args = (<CallExpression>node).arguments || emptyArray;
args = node.arguments || emptyArray;
}
return args;
@@ -13675,10 +13923,11 @@ namespace ts {
function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], headMessage?: DiagnosticMessage): Signature {
const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
const isDecorator = node.kind === SyntaxKind.Decorator;
const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node);
let typeArguments: TypeNode[];
if (!isTaggedTemplate && !isDecorator) {
if (!isTaggedTemplate && !isDecorator && !isJsxOpeningOrSelfClosingElement) {
typeArguments = (<CallExpression>node).typeArguments;
// We already perform checking on the type arguments on the class declaration itself.
@@ -13785,6 +14034,10 @@ namespace ts {
// If candidate is undefined, it means that no candidates had a suitable arity. In that case,
// skip the checkApplicableSignature check.
if (candidateForArgumentError) {
if (isJsxOpeningOrSelfClosingElement) {
// We do not report any error here because any error will be handled in "resolveCustomJsxElementAttributesType".
return candidateForArgumentError;
}
// excludeArgument is undefined, in this case also equivalent to [undefined, undefined, ...]
// The importance of excludeArgument is to prevent us from typing function expression parameters
// in arguments too early. If possible, we'd like to only type them once we know the correct
@@ -13810,7 +14063,7 @@ namespace ts {
diagnosticChainHead = chainDiagnosticMessages(diagnosticChainHead, headMessage);
}
reportNoCommonSupertypeError(inferenceCandidates, (<CallExpression>node).expression || (<TaggedTemplateExpression>node).tag, diagnosticChainHead);
reportNoCommonSupertypeError(inferenceCandidates, (<JsxOpeningLikeElement>node).tagName || (<CallExpression>node).expression || (<TaggedTemplateExpression>node).tag, diagnosticChainHead);
}
}
else {
@@ -14188,6 +14441,53 @@ namespace ts {
return resolveCall(node, callSignatures, candidatesOutArray, headMessage);
}
/**
* This function is similar to getResolvedSignature but is exclusively for trying to resolve JSX stateless-function component.
* The main reason we have to use this function instead of getResolvedSignature because, the caller of this function will already check the type of openingLikeElement's tagName
* and pass the type as elementType. The elementType can not be a union (as such case should be handled by the caller of this function)
* Note: at this point, we are still not sure whether the opening-like element is a stateless function component or not.
* @param openingLikeElement an opening-like JSX element to try to resolve as JSX stateless function
* @param elementType an element type of the opneing-like element by checking opening-like element's tagname.
* @param candidatesOutArray an array of signature to be filled in by the function. It is passed by signature help in the language service;
* the function will fill it up with appropriate candidate signatures
*/
function getResolvedJsxStatelessFunctionSignature(openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[]): Signature {
Debug.assert(!(elementType.flags & TypeFlags.Union));
const callSignature = resolveStatelessJsxOpeningLikeElement(openingLikeElement, elementType, candidatesOutArray);
return callSignature;
}
/**
* Try treating a given opening-like element as stateless function component and resolve a tagName to a function signature.
* @param openingLikeElement an JSX opening-like element we want to try resolve its stateless function if possible
* @param elementType a type of the opening-like JSX element, a result of resolving tagName in opening-like element.
* @param candidatesOutArray an array of signature to be filled in by the function. It is passed by signature help in the language service;
* the function will fill it up with appropriate candidate signatures
* @return a resolved signature if we can find function matching function signature through resolve call or a first signature in the list of functions.
* otherwise return undefined if tag-name of the opening-like element doesn't have call signatures
*/
function resolveStatelessJsxOpeningLikeElement(openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[]): Signature {
// If this function is called from language service, elementType can be a union type. This is not possible if the function is called from compiler (see: resolveCustomJsxElementAttributesType)
if (elementType.flags & TypeFlags.Union) {
const types = (elementType as UnionType).types;
let result: Signature;
for (const type of types) {
result = result || resolveStatelessJsxOpeningLikeElement(openingLikeElement, type, candidatesOutArray);
}
return result;
}
const callSignatures = elementType && getSignaturesOfType(elementType, SignatureKind.Call);
if (callSignatures && callSignatures.length > 0) {
let callSignature: Signature;
callSignature = resolveCall(openingLikeElement, callSignatures, candidatesOutArray);
return callSignature;
}
return undefined;
}
function resolveSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature {
switch (node.kind) {
case SyntaxKind.CallExpression:
@@ -14198,12 +14498,21 @@ namespace ts {
return resolveTaggedTemplateExpression(<TaggedTemplateExpression>node, candidatesOutArray);
case SyntaxKind.Decorator:
return resolveDecorator(<Decorator>node, candidatesOutArray);
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxSelfClosingElement:
// This code-path is called by language service
return resolveStatelessJsxOpeningLikeElement(<JsxOpeningLikeElement>node, checkExpression((<JsxOpeningLikeElement>node).tagName), candidatesOutArray);
}
Debug.fail("Branch in 'resolveSignature' should be unreachable.");
}
// candidatesOutArray is passed by signature help in the language service, and collectCandidates
// must fill it up with the appropriate candidate signatures
/**
* Resolve a signature of a given call-like expression.
* @param node a call-like expression to try resolve a signature for
* @param candidatesOutArray an array of signature to be filled in by the function. It is passed by signature help in the language service;
* the function will fill it up with appropriate candidate signatures
* @return a signature of the call-like expression or undefined if one can't be found
*/
function getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature {
const links = getNodeLinks(node);
// If getResolvedSignature has already been called, we will have cached the resolvedSignature.
@@ -15818,11 +16127,13 @@ namespace ts {
case SyntaxKind.YieldExpression:
return checkYieldExpression(<YieldExpression>node);
case SyntaxKind.JsxExpression:
return checkJsxExpression(<JsxExpression>node);
return checkJsxExpression(<JsxExpression>node, contextualMapper);
case SyntaxKind.JsxElement:
return checkJsxElement(<JsxElement>node);
case SyntaxKind.JsxSelfClosingElement:
return checkJsxSelfClosingElement(<JsxSelfClosingElement>node);
case SyntaxKind.JsxAttributes:
return checkJsxAttributes(<JsxAttributes>node, contextualMapper);
case SyntaxKind.JsxOpeningElement:
Debug.fail("Shouldn't ever directly check a JsxOpeningElement");
}
@@ -22074,7 +22385,8 @@ namespace ts {
function checkGrammarJsxElement(node: JsxOpeningLikeElement) {
const seen = createMap<boolean>();
for (const attr of node.attributes) {
for (const attr of node.attributes.properties) {
if (attr.kind === SyntaxKind.JsxSpreadAttribute) {
continue;
}
+15 -3
View File
@@ -604,6 +604,8 @@ namespace ts {
return emitJsxClosingElement(<JsxClosingElement>node);
case SyntaxKind.JsxAttribute:
return emitJsxAttribute(<JsxAttribute>node);
case SyntaxKind.JsxAttributes:
return emitJsxAttributes(<JsxAttributes>node);
case SyntaxKind.JsxSpreadAttribute:
return emitJsxSpreadAttribute(<JsxSpreadAttribute>node);
case SyntaxKind.JsxExpression:
@@ -1891,15 +1893,21 @@ namespace ts {
write("<");
emitJsxTagName(node.tagName);
write(" ");
emitList(node, node.attributes, ListFormat.JsxElementAttributes);
// We are checking here so we won't re-enter the emiting pipeline and emit extra sourcemap
if (node.attributes.properties && node.attributes.properties.length > 0) {
emit(node.attributes);
}
write("/>");
}
function emitJsxOpeningElement(node: JsxOpeningElement) {
write("<");
emitJsxTagName(node.tagName);
writeIfAny(node.attributes, " ");
emitList(node, node.attributes, ListFormat.JsxElementAttributes);
writeIfAny(node.attributes.properties, " ");
// We are checking here so we won't re-enter the emitting pipeline and emit extra sourcemap
if (node.attributes.properties && node.attributes.properties.length > 0) {
emit(node.attributes);
}
write(">");
}
@@ -1913,6 +1921,10 @@ namespace ts {
write(">");
}
function emitJsxAttributes(node: JsxAttributes) {
emitList(node, node.properties, ListFormat.JsxElementAttributes);
}
function emitJsxAttribute(node: JsxAttribute) {
emit(node.name);
emitWithPrefix("=", node.initializer);
+19 -6
View File
@@ -1381,28 +1381,28 @@ namespace ts {
: node;
}
export function createJsxSelfClosingElement(tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]) {
export function createJsxSelfClosingElement(tagName: JsxTagNameExpression, attributes: JsxAttributes) {
const node = <JsxSelfClosingElement>createSynthesizedNode(SyntaxKind.JsxSelfClosingElement);
node.tagName = tagName;
node.attributes = createNodeArray(attributes);
node.attributes = attributes;
return node;
}
export function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]) {
export function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, attributes: JsxAttributes) {
return node.tagName !== tagName
|| node.attributes !== attributes
? updateNode(createJsxSelfClosingElement(tagName, attributes), node)
: node;
}
export function createJsxOpeningElement(tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]) {
export function createJsxOpeningElement(tagName: JsxTagNameExpression, attributes: JsxAttributes) {
const node = <JsxOpeningElement>createSynthesizedNode(SyntaxKind.JsxOpeningElement);
node.tagName = tagName;
node.attributes = createNodeArray(attributes);
node.attributes = attributes;
return node;
}
export function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]) {
export function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, attributes: JsxAttributes) {
return node.tagName !== tagName
|| node.attributes !== attributes
? updateNode(createJsxOpeningElement(tagName, attributes), node)
@@ -1421,6 +1421,19 @@ namespace ts {
: node;
}
export function createJsxAttributes(properties: JsxAttributeLike[]) {
const jsxAttributes = <JsxAttributes>createSynthesizedNode(SyntaxKind.JsxAttributes);
jsxAttributes.properties = createNodeArray(properties);
return jsxAttributes;
}
export function updateJsxAttributes(jsxAttributes: JsxAttributes, properties: JsxAttributeLike[]) {
if (jsxAttributes.properties !== properties) {
return updateNode(createJsxAttributes(properties), jsxAttributes);
}
return jsxAttributes;
}
export function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression) {
const node = <JsxAttribute>createSynthesizedNode(SyntaxKind.JsxAttribute);
node.name = name;
+10 -2
View File
@@ -369,7 +369,9 @@ namespace ts {
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxOpeningElement:
return visitNode(cbNode, (<JsxOpeningLikeElement>node).tagName) ||
visitNodes(cbNodes, (<JsxOpeningLikeElement>node).attributes);
visitNode(cbNode, (<JsxOpeningLikeElement>node).attributes);
case SyntaxKind.JsxAttributes:
return visitNodes(cbNodes, (<JsxAttributes>node).properties);
case SyntaxKind.JsxAttribute:
return visitNode(cbNode, (<JsxAttribute>node).name) ||
visitNode(cbNode, (<JsxAttribute>node).initializer);
@@ -3870,14 +3872,20 @@ namespace ts {
return result;
}
function parseJsxAttributes(): JsxAttributes {
const jsxAttributes = <JsxAttributes>createNode(SyntaxKind.JsxAttributes);
jsxAttributes.properties = parseList(ParsingContext.JsxAttributes, parseJsxAttribute);
return finishNode(jsxAttributes);
}
function parseJsxOpeningOrSelfClosingElement(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement {
const fullStart = scanner.getStartPos();
parseExpected(SyntaxKind.LessThanToken);
const tagName = parseJsxElementName();
const attributes = parseJsxAttributes();
const attributes = parseList(ParsingContext.JsxAttributes, parseJsxAttribute);
let node: JsxOpeningLikeElement;
if (token() === SyntaxKind.GreaterThanToken) {
+1 -1
View File
@@ -85,7 +85,7 @@ namespace ts {
function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: JsxChild[], isChild: boolean, location: TextRange) {
const tagName = getTagName(node);
let objectProperties: Expression;
const attrs = node.attributes;
const attrs = node.attributes.properties;
if (attrs.length === 0) {
// When there are no attributes, React wants "null"
objectProperties = createNull();
+20 -13
View File
@@ -330,6 +330,7 @@
JsxOpeningElement,
JsxClosingElement,
JsxAttribute,
JsxAttributes,
JsxSpreadAttribute,
JsxExpression,
@@ -727,6 +728,7 @@
// SyntaxKind.BindingElement
// SyntaxKind.Property
// SyntaxKind.PropertyAssignment
// SyntaxKind.JsxAttribute
// SyntaxKind.ShorthandPropertyAssignment
// SyntaxKind.EnumMember
// SyntaxKind.JSDocPropertyTag
@@ -1445,7 +1447,7 @@
template: TemplateLiteral;
}
export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator;
export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement;
export interface AsExpression extends Expression {
kind: SyntaxKind.AsExpression;
@@ -1482,35 +1484,38 @@
closingElement: JsxClosingElement;
}
/// Either the opening tag in a <Tag>...</Tag> pair, or the lone <Tag /> in a self-closing form
export type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement;
export type JsxAttributeLike = JsxAttribute | JsxSpreadAttribute;
export type JsxTagNameExpression = PrimaryExpression | PropertyAccessExpression;
export interface JsxAttributes extends ObjectLiteralExpressionBase<JsxAttributeLike> {
}
/// The opening element of a <Tag>...</Tag> JsxElement
export interface JsxOpeningElement extends Expression {
kind: SyntaxKind.JsxOpeningElement;
tagName: JsxTagNameExpression;
attributes: NodeArray<JsxAttribute | JsxSpreadAttribute>;
attributes: JsxAttributes;
}
/// A JSX expression of the form <TagName attrs />
export interface JsxSelfClosingElement extends PrimaryExpression {
kind: SyntaxKind.JsxSelfClosingElement;
tagName: JsxTagNameExpression;
attributes: NodeArray<JsxAttribute | JsxSpreadAttribute>;
attributes: JsxAttributes;
}
/// Either the opening tag in a <Tag>...</Tag> pair, or the lone <Tag /> in a self-closing form
export type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement;
export type JsxAttributeLike = JsxAttribute | JsxSpreadAttribute;
export interface JsxAttribute extends Node {
export interface JsxAttribute extends ObjectLiteralElement {
kind: SyntaxKind.JsxAttribute;
name: Identifier;
/// JSX attribute initializers are optional; <X y /> is sugar for <X y={true} />
initializer?: StringLiteral | JsxExpression;
}
export interface JsxSpreadAttribute extends Node {
export interface JsxSpreadAttribute extends ObjectLiteralElement {
kind: SyntaxKind.JsxSpreadAttribute;
expression: Expression;
}
@@ -2421,7 +2426,7 @@
/** Unlike `getExportsOfModule`, this includes properties of an `export =` value. */
/* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[];
getJsxElementAttributesType(elementNode: JsxOpeningLikeElement): Type;
getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type;
getJsxIntrinsicTagNames(): Symbol[];
isOptionalParameter(node: ParameterDeclaration): boolean;
getAmbientModules(): Symbol[];
@@ -2814,7 +2819,7 @@
isVisible?: boolean; // Is this node visible
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with
resolvedJsxType?: Type; // resolved element attributes type of a JSX openinglike element
resolvedJsxElementAttributesType?: Type; // resolved element attributes type of a JSX openinglike element
hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt.
superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
switchTypes?: Type[]; // Cached array of switch case expression types
@@ -2850,6 +2855,8 @@
/* @internal */
ContainsAnyFunctionType = 1 << 23, // Type is or contains object literal type
NonPrimitive = 1 << 24, // intrinsic object type
/* @internal */
JsxAttributes = 1 << 25, // Jsx attributes type
/* @internal */
Nullable = Undefined | Null,
@@ -3039,7 +3046,7 @@
/* @internal */
// Object literals are initially marked fresh. Freshness disappears following an assignment,
// before a type assertion, or when when an object literal's type is widened. The regular
// before a type assertion, or when an object literal's type is widened. The regular
// version of a fresh type is identical except for the TypeFlags.FreshObjectLiteral flag.
export interface FreshObjectLiteralType extends ResolvedType {
regularType: ResolvedType; // Regular version of fresh type
+15
View File
@@ -1178,6 +1178,8 @@ namespace ts {
export function isCallLikeExpression(node: Node): node is CallLikeExpression {
switch (node.kind) {
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TaggedTemplateExpression:
@@ -1192,6 +1194,9 @@ namespace ts {
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
return (<TaggedTemplateExpression>node).tag;
}
else if (isJsxOpeningLikeElement(node)) {
return node.tagName;
}
// Will either be a CallExpression, NewExpression, or Decorator.
return (<CallExpression | Decorator>node).expression;
@@ -3963,6 +3968,7 @@ namespace ts {
|| kind === SyntaxKind.ImportEqualsDeclaration
|| kind === SyntaxKind.ImportSpecifier
|| kind === SyntaxKind.InterfaceDeclaration
|| kind === SyntaxKind.JsxAttribute
|| kind === SyntaxKind.MethodDeclaration
|| kind === SyntaxKind.MethodSignature
|| kind === SyntaxKind.ModuleDeclaration
@@ -4075,6 +4081,11 @@ namespace ts {
|| kind === SyntaxKind.JsxText;
}
export function isJsxAttributes(node: Node): node is JsxAttributes {
const kind = node.kind;
return kind === SyntaxKind.JsxAttributes;
}
export function isJsxAttributeLike(node: Node): node is JsxAttributeLike {
const kind = node.kind;
return kind === SyntaxKind.JsxAttribute
@@ -4089,6 +4100,10 @@ namespace ts {
return node.kind === SyntaxKind.JsxAttribute;
}
export function isJsxOpeningLikeElement(node: Node): node is JsxOpeningLikeElement {
return node.kind === SyntaxKind.JsxOpeningElement || node.kind === SyntaxKind.JsxSelfClosingElement;
}
export function isStringLiteralOrJsxExpression(node: Node): node is StringLiteral | JsxExpression {
const kind = node.kind;
return kind === SyntaxKind.StringLiteral
+11 -3
View File
@@ -426,13 +426,17 @@ namespace ts {
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxOpeningElement:
result = reduceNode((<JsxSelfClosingElement | JsxOpeningElement>node).tagName, cbNode, result);
result = reduceNodes((<JsxSelfClosingElement | JsxOpeningElement>node).attributes, cbNodes, result);
result = reduceNode((<JsxSelfClosingElement | JsxOpeningElement>node).attributes, cbNode, result);
break;
case SyntaxKind.JsxClosingElement:
result = reduceNode((<JsxClosingElement>node).tagName, cbNode, result);
break;
case SyntaxKind.JsxAttributes:
result = reduceNodes((<JsxAttributes>node).properties, cbNodes, result);
break;
case SyntaxKind.JsxAttribute:
result = reduceNode((<JsxAttribute>node).name, cbNode, result);
result = reduceNode((<JsxAttribute>node).initializer, cbNode, result);
@@ -1108,15 +1112,19 @@ namespace ts {
visitNodes((<JsxElement>node).children, visitor, isJsxChild),
visitNode((<JsxElement>node).closingElement, visitor, isJsxClosingElement));
case SyntaxKind.JsxAttributes:
return updateJsxAttributes(<JsxAttributes>node,
visitNodes((<JsxAttributes>node).properties, visitor, isJsxAttributeLike));
case SyntaxKind.JsxSelfClosingElement:
return updateJsxSelfClosingElement(<JsxSelfClosingElement>node,
visitNode((<JsxSelfClosingElement>node).tagName, visitor, isJsxTagNameExpression),
visitNodes((<JsxSelfClosingElement>node).attributes, visitor, isJsxAttributeLike));
visitNode((<JsxSelfClosingElement>node).attributes, visitor, isJsxAttributes));
case SyntaxKind.JsxOpeningElement:
return updateJsxOpeningElement(<JsxOpeningElement>node,
visitNode((<JsxOpeningElement>node).tagName, visitor, isJsxTagNameExpression),
visitNodes((<JsxOpeningElement>node).attributes, visitor, isJsxAttributeLike));
visitNode((<JsxOpeningElement>node).attributes, visitor, isJsxAttributes));
case SyntaxKind.JsxClosingElement:
return updateJsxClosingElement(<JsxClosingElement>node,
+32 -3
View File
@@ -922,10 +922,15 @@ namespace Harness {
export const defaultLibFileName = "lib.d.ts";
export const es2015DefaultLibFileName = "lib.es2015.d.ts";
// Cache of lib files from "built/local"
const libFileNameSourceFileMap = ts.createMapFromTemplate<ts.SourceFile>({
[defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest)
});
// Cache of lib files from "tests/lib/"
const testLibFileNameSourceFileMap = ts.createMap<ts.SourceFile>();
const es6TestLibFileNameSourceFileMap = ts.createMap<ts.SourceFile>();
export function getDefaultLibrarySourceFile(fileName = defaultLibFileName): ts.SourceFile {
if (!isDefaultLibraryFile(fileName)) {
return undefined;
@@ -967,7 +972,8 @@ namespace Harness {
useCaseSensitiveFileNames: boolean,
// the currentDirectory is needed for rwcRunner to passed in specified current directory to compiler host
currentDirectory: string,
newLineKind?: ts.NewLineKind): ts.CompilerHost {
newLineKind?: ts.NewLineKind,
libFiles?: string): ts.CompilerHost {
// Local get canonical file name function, that depends on passed in parameter for useCaseSensitiveFileNames
const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames);
@@ -999,6 +1005,24 @@ namespace Harness {
}
}
if (libFiles) {
// Because @libFiles don't change between execution. We would cache the result of the files and reuse it to speed help compilation
for (const fileName of libFiles.split(",")) {
const libFileName = "tests/lib/" + fileName;
if (scriptTarget <= ts.ScriptTarget.ES5) {
if (!testLibFileNameSourceFileMap.get(libFileName)) {
testLibFileNameSourceFileMap.set(libFileName, createSourceFileAndAssertInvariants(libFileName, IO.readFile(libFileName), scriptTarget));
}
}
else {
if (!es6TestLibFileNameSourceFileMap.get(libFileName)) {
es6TestLibFileNameSourceFileMap.set(libFileName, createSourceFileAndAssertInvariants(libFileName, IO.readFile(libFileName), scriptTarget))
}
}
}
}
function getSourceFile(fileName: string) {
fileName = ts.normalizePath(fileName);
const fromFileMap = fileMap.get(toPath(fileName));
@@ -1010,6 +1034,9 @@ namespace Harness {
fourslashSourceFile = fourslashSourceFile || createSourceFileAndAssertInvariants(tsFn, Harness.IO.readFile(tsFn), scriptTarget);
return fourslashSourceFile;
}
else if (ts.startsWith(fileName, "tests/lib/")) {
return scriptTarget <= ts.ScriptTarget.ES5 ? testLibFileNameSourceFileMap.get(fileName) : es6TestLibFileNameSourceFileMap.get(fileName);
}
else {
// Don't throw here -- the compiler might be looking for a test that actually doesn't exist as part of the TC
// Return if it is other library file, otherwise return undefined
@@ -1221,7 +1248,8 @@ namespace Harness {
if (options.libFiles) {
for (const fileName of options.libFiles.split(",")) {
const libFileName = "tests/lib/" + fileName;
programFiles.push({ unitName: libFileName, content: normalizeLineEndings(IO.readFile(libFileName), Harness.IO.newLine()) });
// Content is undefined here because in createCompilerHost we will create sourceFile for the lib file and cache the result
programFiles.push({ unitName: libFileName, content: undefined });
}
}
@@ -1234,7 +1262,8 @@ namespace Harness {
options.target,
useCaseSensitiveFileNames,
currentDirectory,
options.newLine);
options.newLine,
options.libFiles);
let traceResults: string[];
if (options.traceResolution) {
+25 -8
View File
@@ -1056,10 +1056,10 @@ namespace ts.Completions {
let attrsType: Type;
if ((jsxContainer.kind === SyntaxKind.JsxSelfClosingElement) || (jsxContainer.kind === SyntaxKind.JsxOpeningElement)) {
// Cursor is inside a JSX self-closing element or opening element
attrsType = typeChecker.getJsxElementAttributesType(<JsxOpeningLikeElement>jsxContainer);
attrsType = typeChecker.getAllAttributesTypeFromJsxOpeningLikeElement(<JsxOpeningLikeElement>jsxContainer);
if (attrsType) {
symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), (<JsxOpeningLikeElement>jsxContainer).attributes);
symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), (<JsxOpeningLikeElement>jsxContainer).attributes.properties);
isMemberCompletion = true;
isNewIdentifierLocation = false;
return true;
@@ -1401,13 +1401,18 @@ namespace ts.Completions {
case SyntaxKind.LessThanSlashToken:
case SyntaxKind.SlashToken:
case SyntaxKind.Identifier:
case SyntaxKind.JsxAttributes:
case SyntaxKind.JsxAttribute:
case SyntaxKind.JsxSpreadAttribute:
if (parent && (parent.kind === SyntaxKind.JsxSelfClosingElement || parent.kind === SyntaxKind.JsxOpeningElement)) {
return <JsxOpeningLikeElement>parent;
}
else if (parent.kind === SyntaxKind.JsxAttribute) {
return <JsxOpeningLikeElement>parent.parent;
// Currently we parse JsxOpeningLikeElement as:
// JsxOpeningLikeElement
// attributes: JsxAttributes
// properties: NodeArray<JsxAttributeLike>
return parent.parent.parent as JsxOpeningLikeElement;
}
break;
@@ -1416,7 +1421,11 @@ namespace ts.Completions {
// whose parent is a JsxOpeningLikeElement
case SyntaxKind.StringLiteral:
if (parent && ((parent.kind === SyntaxKind.JsxAttribute) || (parent.kind === SyntaxKind.JsxSpreadAttribute))) {
return <JsxOpeningLikeElement>parent.parent;
// Currently we parse JsxOpeningLikeElement as:
// JsxOpeningLikeElement
// attributes: JsxAttributes
// properties: NodeArray<JsxAttributeLike>
return parent.parent.parent as JsxOpeningLikeElement;
}
break;
@@ -1424,13 +1433,21 @@ namespace ts.Completions {
case SyntaxKind.CloseBraceToken:
if (parent &&
parent.kind === SyntaxKind.JsxExpression &&
parent.parent &&
(parent.parent.kind === SyntaxKind.JsxAttribute)) {
return <JsxOpeningLikeElement>parent.parent.parent;
parent.parent && parent.parent.kind === SyntaxKind.JsxAttribute) {
// Currently we parse JsxOpeningLikeElement as:
// JsxOpeningLikeElement
// attributes: JsxAttributes
// properties: NodeArray<JsxAttributeLike>
// each JsxAttribute can have initializer as JsxExpression
return parent.parent.parent.parent as JsxOpeningLikeElement;
}
if (parent && parent.kind === SyntaxKind.JsxSpreadAttribute) {
return <JsxOpeningLikeElement>parent.parent;
// Currently we parse JsxOpeningLikeElement as:
// JsxOpeningLikeElement
// attributes: JsxAttributes
// properties: NodeArray<JsxAttributeLike>
return parent.parent.parent as JsxOpeningLikeElement;
}
break;
-29
View File
@@ -1416,35 +1416,6 @@ namespace ts.FindAllReferences {
});
}
/**
* Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
*/
function getContainingObjectLiteralElement(node: Node): ObjectLiteralElement {
switch (node.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
if (node.parent.kind === SyntaxKind.ComputedPropertyName) {
return isObjectLiteralPropertyDeclaration(node.parent.parent) ? node.parent.parent : undefined;
}
// intential fall through
case SyntaxKind.Identifier:
return isObjectLiteralPropertyDeclaration(node.parent) && node.parent.name === node ? node.parent : undefined;
}
return undefined;
}
function isObjectLiteralPropertyDeclaration(node: Node): node is ObjectLiteralElement {
switch (node.kind) {
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return true;
}
return false;
}
/** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */
function tryGetClassByExtendingIdentifier(node: Node): ClassLikeDeclaration | undefined {
return tryGetClassExtendingExpressionWithTypeArguments(climbPastPropertyAccess(node).parent);
+38 -4
View File
@@ -1,4 +1,4 @@
/* @internal */
/* @internal */
namespace ts.GoToDefinition {
export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): DefinitionInfo[] {
/// Triple slash reference comments
@@ -85,6 +85,37 @@ namespace ts.GoToDefinition {
declaration => createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName));
}
if (isJsxOpeningLikeElement(node.parent)) {
// If there are errors when trying to figure out stateless component function, just return the first declaration
// For example:
// declare function /*firstSource*/MainButton(buttonProps: ButtonProps): JSX.Element;
// declare function /*secondSource*/MainButton(linkProps: LinkProps): JSX.Element;
// declare function /*thirdSource*/MainButton(props: ButtonProps | LinkProps): JSX.Element;
// let opt = <Main/*firstTarget*/Button />; // Error - We get undefined for resolved signature indicating an error, then just return the first declaration
const {symbolName, symbolKind, containerName} = getSymbolInfo(typeChecker, symbol, node);
return [createDefinitionInfo(symbol.valueDeclaration, symbolKind, symbolName, containerName)];
}
// If the current location we want to find its definition is in an object literal, try to get the contextual type for the
// object literal, lookup the property symbol in the contextual type, and use this for goto-definition.
// For example
// interface Props{
// /*first*/prop1: number
// prop2: boolean
// }
// function Foo(arg: Props) {}
// Foo( { pr/*1*/op1: 10, prop2: true })
const element = getContainingObjectLiteralElement(node);
if (element) {
if (typeChecker.getContextualType(element.parent as Expression)) {
const result: DefinitionInfo[] = [];
const propertySymbols = getPropertySymbolsFromContextualType(typeChecker, element);
for (const propertySymbol of propertySymbols) {
result.push(...getDefinitionFromSymbol(typeChecker, propertySymbol, node));
}
return result;
}
}
return getDefinitionFromSymbol(typeChecker, symbol, node);
}
@@ -262,9 +293,12 @@ namespace ts.GoToDefinition {
function tryGetSignatureDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined {
const callLike = getAncestorCallLikeExpression(node);
const decl = callLike && typeChecker.getResolvedSignature(callLike).declaration;
if (decl && isSignatureDeclaration(decl)) {
return decl;
const signature = callLike && typeChecker.getResolvedSignature(callLike);
if (signature) {
const decl = signature.declaration;
if (decl && isSignatureDeclaration(decl)) {
return decl;
}
}
// Don't go to a function type, go to the value having that type.
return undefined;
+60
View File
@@ -1991,6 +1991,66 @@ namespace ts {
}
}
function isObjectLiteralElement(node: Node): node is ObjectLiteralElement {
switch (node.kind) {
case SyntaxKind.JsxAttribute:
case SyntaxKind.JsxSpreadAttribute:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return true;
}
return false;
}
/**
* Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
*/
/* @internal */
export function getContainingObjectLiteralElement(node: Node): ObjectLiteralElement {
switch (node.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
if (node.parent.kind === SyntaxKind.ComputedPropertyName) {
return isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined;
}
// intentionally fall through
case SyntaxKind.Identifier:
return isObjectLiteralElement(node.parent) &&
(node.parent.parent.kind === SyntaxKind.ObjectLiteralExpression || node.parent.parent.kind === SyntaxKind.JsxAttributes) &&
(<ObjectLiteralElement>node.parent).name === node ? node.parent as ObjectLiteralElement : undefined;
}
return undefined;
}
/* @internal */
export function getPropertySymbolsFromContextualType(typeChecker: TypeChecker, node: ObjectLiteralElement): Symbol[] {
const objectLiteral = <ObjectLiteralExpression | JsxAttributes>node.parent;
const contextualType = typeChecker.getContextualType(objectLiteral);
const name = getTextOfPropertyName(node.name);
if (name && contextualType) {
const result: Symbol[] = [];
const symbol = contextualType.getProperty(name);
if (contextualType.flags & TypeFlags.Union) {
forEach((<UnionType>contextualType).types, t => {
const symbol = t.getProperty(name);
if (symbol) {
result.push(symbol);
}
});
return result;
}
if (symbol) {
result.push(symbol);
return result;
}
}
return undefined;
}
function isArgumentOfElementAccessExpression(node: Node) {
return node &&
node.parent &&
+24 -8
View File
@@ -168,7 +168,8 @@ namespace ts.SignatureHelp {
export const enum ArgumentListKind {
TypeArguments,
CallArguments,
TaggedTemplateArguments
TaggedTemplateArguments,
JSXAttributesArguments
}
export interface ArgumentListInfo {
@@ -264,18 +265,18 @@ namespace ts.SignatureHelp {
if (node.parent.kind === SyntaxKind.CallExpression || node.parent.kind === SyntaxKind.NewExpression) {
const callExpression = <CallExpression>node.parent;
// There are 3 cases to handle:
// 1. The token introduces a list, and should begin a sig help session
// 1. The token introduces a list, and should begin a signature help session
// 2. The token is either not associated with a list, or ends a list, so the session should end
// 3. The token is buried inside a list, and should give sig help
// 3. The token is buried inside a list, and should give signature help
//
// The following are examples of each:
//
// Case 1:
// foo<#T, U>(#a, b) -> The token introduces a list, and should begin a sig help session
// foo<#T, U>(#a, b) -> The token introduces a list, and should begin a signature help session
// Case 2:
// fo#o<T, U>#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end
// Case 3:
// foo<T#, U#>(a#, #b#) -> The token is buried inside a list, and should give sig help
// foo<T#, U#>(a#, #b#) -> The token is buried inside a list, and should give signature help
// Find out if 'node' is an argument, a type argument, or neither
if (node.kind === SyntaxKind.LessThanToken ||
node.kind === SyntaxKind.OpenParenToken) {
@@ -295,7 +296,7 @@ namespace ts.SignatureHelp {
// findListItemInfo can return undefined if we are not in parent's argument list
// or type argument list. This includes cases where the cursor is:
// - To the right of the closing paren, non-substitution template, or template tail.
// - To the right of the closing parenthesis, non-substitution template, or template tail.
// - Between the type arguments and the arguments (greater than token)
// - On the target of the call (parent.func)
// - On the 'new' keyword in a 'new' expression
@@ -352,6 +353,22 @@ namespace ts.SignatureHelp {
return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile);
}
else if (node.parent && isJsxOpeningLikeElement(node.parent)) {
// Provide a signature help for JSX opening element or JSX self-closing element.
// This is not guarantee that JSX tag-name is resolved into stateless function component. (that is done in "getSignatureHelpItems")
// i.e
// export function MainButton(props: ButtonProps, context: any): JSX.Element { ... }
// <MainButton /*signatureHelp*/
const attributeSpanStart = node.parent.attributes.getFullStart();
const attributeSpanEnd = skipTrivia(sourceFile.text, node.parent.attributes.getEnd(), /*stopAfterLineBreak*/ false);
return {
kind: ArgumentListKind.JSXAttributesArguments,
invocation: node.parent,
argumentsSpan: createTextSpan(attributeSpanStart, attributeSpanEnd - attributeSpanStart),
argumentIndex: 0,
argumentCount: 1
};
}
return undefined;
}
@@ -392,7 +409,7 @@ namespace ts.SignatureHelp {
//
// Note: this subtlety only applies to the last comma. If you had "Foo(a,," then
// we'll have: 'a' '<comma>' '<missing>'
// That will give us 2 non-commas. We then add one for the last comma, givin us an
// That will give us 2 non-commas. We then add one for the last comma, giving us an
// arg count of 3.
const listChildren = argumentsList.getChildren();
@@ -435,7 +452,6 @@ namespace ts.SignatureHelp {
: (<TemplateExpression>tagExpression.template).templateSpans.length + 1;
Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`);
return {
kind: ArgumentListKind.TaggedTemplateArguments,
invocation: tagExpression,
+15 -6
View File
@@ -71,6 +71,9 @@ namespace ts.SymbolDisplay {
}
return unionPropertyKind;
}
if (location.parent && isJsxAttribute(location.parent)) {
return ScriptElementKind.jsxAttribute;
}
return ScriptElementKind.memberVariableElement;
}
@@ -114,23 +117,27 @@ namespace ts.SymbolDisplay {
}
// try get the call/construct signature from the type if it matches
let callExpression: CallExpression | NewExpression;
let callExpressionLike: CallExpression | NewExpression | JsxOpeningLikeElement;
if (location.kind === SyntaxKind.CallExpression || location.kind === SyntaxKind.NewExpression) {
callExpression = <CallExpression | NewExpression>location;
callExpressionLike = <CallExpression | NewExpression>location;
}
else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) {
callExpression = <CallExpression | NewExpression>location.parent;
callExpressionLike = <CallExpression | NewExpression>location.parent;
}
else if (location.parent && isJsxOpeningLikeElement(location.parent) && isFunctionLike(symbol.valueDeclaration)) {
callExpressionLike = <JsxOpeningLikeElement>location.parent;
}
if (callExpression) {
if (callExpressionLike) {
const candidateSignatures: Signature[] = [];
signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures);
signature = typeChecker.getResolvedSignature(callExpressionLike, candidateSignatures);
if (!signature && candidateSignatures.length) {
// Use the first candidate:
signature = candidateSignatures[0];
}
const useConstructSignatures = callExpression.kind === SyntaxKind.NewExpression || callExpression.expression.kind === SyntaxKind.SuperKeyword;
const useConstructSignatures = callExpressionLike.kind === SyntaxKind.NewExpression || (isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === SyntaxKind.SuperKeyword);
const allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures();
if (!contains(allSignatures, signature.target) && !contains(allSignatures, signature)) {
@@ -160,6 +167,7 @@ namespace ts.SymbolDisplay {
}
switch (symbolKind) {
case ScriptElementKind.jsxAttribute:
case ScriptElementKind.memberVariableElement:
case ScriptElementKind.variableElement:
case ScriptElementKind.constElement:
@@ -373,6 +381,7 @@ namespace ts.SymbolDisplay {
// For properties, variables and local vars: show the type
if (symbolKind === ScriptElementKind.memberVariableElement ||
symbolKind === ScriptElementKind.jsxAttribute ||
symbolFlags & SymbolFlags.Variable ||
symbolKind === ScriptElementKind.localVariableElement ||
isThisExpression) {
+5
View File
@@ -765,6 +765,11 @@ namespace ts {
export const directory = "directory";
export const externalModuleName = "external module name";
/**
* <JsxTagName attribute1 attribute2={0} />
**/
export const jsxAttribute = "JSX attribute";
}
export namespace ScriptElementKindModifier {
+1
View File
@@ -31,6 +31,7 @@ namespace ts {
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.CatchClause:
case SyntaxKind.JsxAttribute:
return SemanticMeaning.Value;
case SyntaxKind.TypeParameter:
@@ -1,5 +1,9 @@
tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx(16,15): error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx(17,15): error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx(16,15): error TS2322: Type '{ foo: "f"; }' is not assignable to type '{ foo: "A" | "B" | "C"; }'.
Types of property 'foo' are incompatible.
Type '"f"' is not assignable to type '"A" | "B" | "C"'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx(17,15): error TS2322: Type '{ foo: "f"; }' is not assignable to type '{ foo: "A" | "B" | "C"; }'.
Types of property 'foo' are incompatible.
Type '"f"' is not assignable to type '"A" | "B" | "C"'.
==== tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx (2 errors) ====
@@ -20,7 +24,11 @@ tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStr
<FooComponent foo={"f"} />;
~~~~~~~~~
!!! error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'.
!!! error TS2322: Type '{ foo: "f"; }' is not assignable to type '{ foo: "A" | "B" | "C"; }'.
!!! error TS2322: Types of property 'foo' are incompatible.
!!! error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'.
<FooComponent foo="f" />;
~~~~~~~
!!! error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'.
!!! error TS2322: Type '{ foo: "f"; }' is not assignable to type '{ foo: "A" | "B" | "C"; }'.
!!! error TS2322: Types of property 'foo' are incompatible.
!!! error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'.
@@ -0,0 +1,71 @@
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(28,24): error TS2322: Type '{ extra: true; onClick: (k: "left" | "right") => void; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(29,24): error TS2322: Type '{ onClick: (k: "left" | "right") => void; extra: true; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
Property 'onClick' does not exist on type 'IntrinsicAttributes & LinkProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(30,24): error TS2322: Type '{ extra: true; goTo: "home"; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(31,24): error TS2322: Type '{ goTo: "home"; extra: true; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(34,25): error TS2322: Type '{ extra: true; onClick: (k: "left" | "right") => void; }' is not assignable to type 'IntrinsicAttributes & ButtonProps'.
Property 'extra' does not exist on type 'IntrinsicAttributes & ButtonProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(37,25): error TS2322: Type '{ extra: true; goTo: "home"; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
==== tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx (6 errors) ====
import React = require('react')
export interface ClickableProps {
children?: string;
className?: string;
}
export interface ButtonProps extends ClickableProps {
onClick: (k: "left" | "right") => void;
}
export interface LinkProps extends ClickableProps {
goTo: "home" | "contact";
}
export function MainButton(buttonProps: ButtonProps): JSX.Element;
export function MainButton(linkProps: LinkProps): JSX.Element;
export function MainButton(props: ButtonProps | LinkProps): JSX.Element {
const linkProps = props as LinkProps;
if(linkProps.goTo) {
return this._buildMainLink(props);
}
return this._buildMainButton(props);
}
const b0 = <MainButton {...{onClick: (k) => {console.log(k)}}} extra />; // k has type "left" | "right"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ extra: true; onClick: (k: "left" | "right") => void; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
!!! error TS2322: Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
const b2 = <MainButton onClick={(k)=>{console.log(k)}} extra />; // k has type "left" | "right"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ onClick: (k: "left" | "right") => void; extra: true; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
!!! error TS2322: Property 'onClick' does not exist on type 'IntrinsicAttributes & LinkProps'.
const b3 = <MainButton {...{goTo:"home"}} extra />; // goTo has type"home" | "contact"
~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ extra: true; goTo: "home"; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
!!! error TS2322: Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
const b4 = <MainButton goTo="home" extra />; // goTo has type "home" | "contact"
~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ goTo: "home"; extra: true; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
!!! error TS2322: Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
export function NoOverload(buttonProps: ButtonProps): JSX.Element { return undefined }
const c1 = <NoOverload {...{onClick: (k) => {console.log(k)}}} extra />; // k has type any
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ extra: true; onClick: (k: "left" | "right") => void; }' is not assignable to type 'IntrinsicAttributes & ButtonProps'.
!!! error TS2322: Property 'extra' does not exist on type 'IntrinsicAttributes & ButtonProps'.
export function NoOverload1(linkProps: LinkProps): JSX.Element { return undefined }
const d1 = <NoOverload1 {...{goTo:"home"}} extra />; // goTo has type "home" | "contact"
~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ extra: true; goTo: "home"; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
!!! error TS2322: Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
@@ -0,0 +1,63 @@
//// [file.tsx]
import React = require('react')
export interface ClickableProps {
children?: string;
className?: string;
}
export interface ButtonProps extends ClickableProps {
onClick: (k: "left" | "right") => void;
}
export interface LinkProps extends ClickableProps {
goTo: "home" | "contact";
}
export function MainButton(buttonProps: ButtonProps): JSX.Element;
export function MainButton(linkProps: LinkProps): JSX.Element;
export function MainButton(props: ButtonProps | LinkProps): JSX.Element {
const linkProps = props as LinkProps;
if(linkProps.goTo) {
return this._buildMainLink(props);
}
return this._buildMainButton(props);
}
const b0 = <MainButton {...{onClick: (k) => {console.log(k)}}} extra />; // k has type "left" | "right"
const b2 = <MainButton onClick={(k)=>{console.log(k)}} extra />; // k has type "left" | "right"
const b3 = <MainButton {...{goTo:"home"}} extra />; // goTo has type"home" | "contact"
const b4 = <MainButton goTo="home" extra />; // goTo has type "home" | "contact"
export function NoOverload(buttonProps: ButtonProps): JSX.Element { return undefined }
const c1 = <NoOverload {...{onClick: (k) => {console.log(k)}}} extra />; // k has type any
export function NoOverload1(linkProps: LinkProps): JSX.Element { return undefined }
const d1 = <NoOverload1 {...{goTo:"home"}} extra />; // goTo has type "home" | "contact"
//// [file.jsx]
define(["require", "exports", "react"], function (require, exports, React) {
"use strict";
exports.__esModule = true;
function MainButton(props) {
var linkProps = props;
if (linkProps.goTo) {
return this._buildMainLink(props);
}
return this._buildMainButton(props);
}
exports.MainButton = MainButton;
var b0 = <MainButton {...{ onClick: function (k) { console.log(k); } }} extra/>; // k has type "left" | "right"
var b2 = <MainButton onClick={function (k) { console.log(k); }} extra/>; // k has type "left" | "right"
var b3 = <MainButton {...{ goTo: "home" }} extra/>; // goTo has type"home" | "contact"
var b4 = <MainButton goTo="home" extra/>; // goTo has type "home" | "contact"
function NoOverload(buttonProps) { return undefined; }
exports.NoOverload = NoOverload;
var c1 = <NoOverload {...{ onClick: function (k) { console.log(k); } }} extra/>; // k has type any
function NoOverload1(linkProps) { return undefined; }
exports.NoOverload1 = NoOverload1;
var d1 = <NoOverload1 {...{ goTo: "home" }} extra/>; // goTo has type "home" | "contact"
});
@@ -5,5 +5,5 @@ declare var React: any;
<foo data/>
>foo : Symbol(unknown)
>data : Symbol(unknown)
>data : Symbol(data, Decl(jsxEmitAttributeWithPreserve.tsx, 2, 4))
@@ -6,5 +6,5 @@ declare var React: any;
<foo data/>
><foo data/> : any
>foo : any
>data : any
>data : true
@@ -101,12 +101,12 @@ class A {
return [
<meta content="helloworld"></meta>,
>meta : Symbol(unknown)
>content : Symbol(unknown)
>content : Symbol(content, Decl(test.tsx, 11, 8))
>meta : Symbol(unknown)
<meta content={c.a!.b}></meta>
>meta : Symbol(unknown)
>content : Symbol(unknown)
>content : Symbol(content, Decl(test.tsx, 12, 8))
>c.a!.b : Symbol(b, Decl(test.tsx, 3, 6))
>c.a : Symbol(a, Decl(test.tsx, 2, 8))
>c : Symbol(c, Decl(test.tsx, 2, 3))
@@ -114,13 +114,13 @@ class A {
<meta content="helloworld"></meta>,
><meta content="helloworld"></meta> : any
>meta : any
>content : any
>content : string
>meta : any
<meta content={c.a!.b}></meta>
><meta content={c.a!.b}></meta> : any
>meta : any
>content : any
>content : string
>c.a!.b : string
>c.a! : { b: string; }
>c.a : { b: string; }
@@ -107,12 +107,12 @@ class A {
return [
<meta content="helloworld"></meta>,
>meta : Symbol(unknown)
>content : Symbol(unknown)
>content : Symbol(content, Decl(test.tsx, 11, 8))
>meta : Symbol(unknown)
<meta content={c.a!.b}></meta>
>meta : Symbol(unknown)
>content : Symbol(unknown)
>content : Symbol(content, Decl(test.tsx, 12, 8))
>c.a!.b : Symbol(b, Decl(test.tsx, 3, 6))
>c.a : Symbol(a, Decl(test.tsx, 2, 8))
>c : Symbol(c, Decl(test.tsx, 2, 3))
@@ -120,13 +120,13 @@ class A {
<meta content="helloworld"></meta>,
><meta content="helloworld"></meta> : any
>meta : any
>content : any
>content : string
>meta : any
<meta content={c.a!.b}></meta>
><meta content={c.a!.b}></meta> : any
>meta : any
>content : any
>content : string
>c.a!.b : string
>c.a! : { b: string; }
>c.a : { b: string; }
@@ -101,12 +101,12 @@ class A {
return [
<meta content="helloworld"></meta>,
>meta : Symbol(unknown)
>content : Symbol(unknown)
>content : Symbol(content, Decl(test.tsx, 11, 8))
>meta : Symbol(unknown)
<meta content={c.a!.b}></meta>
>meta : Symbol(unknown)
>content : Symbol(unknown)
>content : Symbol(content, Decl(test.tsx, 12, 8))
>c.a!.b : Symbol(b, Decl(test.tsx, 3, 6))
>c.a : Symbol(a, Decl(test.tsx, 2, 8))
>c : Symbol(c, Decl(test.tsx, 2, 3))
@@ -114,13 +114,13 @@ class A {
<meta content="helloworld"></meta>,
><meta content="helloworld"></meta> : any
>meta : any
>content : any
>content : string
>meta : any
<meta content={c.a!.b}></meta>
><meta content={c.a!.b}></meta> : any
>meta : any
>content : any
>content : string
>c.a!.b : string
>c.a! : { b: string; }
>c.a : { b: string; }
@@ -9,7 +9,7 @@ let x = Test; // emit test_1.default
<anything attr={Test} />; // ?
>anything : Symbol(unknown)
>attr : Symbol(unknown)
>attr : Symbol(attr, Decl(consumer.tsx, 4, 9))
>Test : Symbol(Test, Decl(consumer.tsx, 1, 6))
=== tests/cases/compiler/component.d.ts ===
@@ -10,7 +10,7 @@ let x = Test; // emit test_1.default
<anything attr={Test} />; // ?
><anything attr={Test} /> : any
>anything : any
>attr : any
>attr : typeof Test
>Test : typeof Test
=== tests/cases/compiler/component.d.ts ===
@@ -92,26 +92,26 @@ var x =
>div : Symbol(unknown)
attr1={
>attr1 : Symbol(unknown)
>attr1 : Symbol(attr1, Decl(jsxReactTestSuite.tsx, 36, 6))
"foo" + "bar"
}
attr2={
>attr2 : Symbol(unknown)
>attr2 : Symbol(attr2, Decl(jsxReactTestSuite.tsx, 39, 5))
"foo" + "bar" +
"baz" + "bug"
}
attr3={
>attr3 : Symbol(unknown)
>attr3 : Symbol(attr3, Decl(jsxReactTestSuite.tsx, 44, 5))
"foo" + "bar" +
"baz" + "bug"
// Extra line here.
}
attr4="baz">
>attr4 : Symbol(unknown)
>attr4 : Symbol(attr4, Decl(jsxReactTestSuite.tsx, 49, 5))
</div>;
>div : Symbol(unknown)
@@ -147,13 +147,13 @@ var x =
/* a multi-line
comment */
attr1="foo">
>attr1 : Symbol(unknown)
>attr1 : Symbol(attr1, Decl(jsxReactTestSuite.tsx, 68, 6))
<span // a double-slash comment
>span : Symbol(unknown)
attr2="bar"
>attr2 : Symbol(unknown)
>attr2 : Symbol(attr2, Decl(jsxReactTestSuite.tsx, 72, 9))
/>
</div>
@@ -175,7 +175,7 @@ var x =
<Component constructor="foo" />;
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
>constructor : Symbol(unknown)
>constructor : Symbol(constructor, Decl(jsxReactTestSuite.tsx, 84, 10))
<Namespace.Component />;
>Namespace : Symbol(Namespace, Decl(jsxReactTestSuite.tsx, 6, 11))
@@ -186,23 +186,23 @@ var x =
<Component { ... x } y
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
>x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3))
>y : Symbol(unknown)
>y : Symbol(y, Decl(jsxReactTestSuite.tsx, 90, 20))
={2 } z />;
>z : Symbol(unknown)
>z : Symbol(z, Decl(jsxReactTestSuite.tsx, 91, 5))
<Component
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
{...this.props} sound="moo" />;
>sound : Symbol(unknown)
>sound : Symbol(sound, Decl(jsxReactTestSuite.tsx, 94, 19))
<font-face />;
>font-face : Symbol(unknown)
<Component x={y} />;
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
>x : Symbol(unknown)
>x : Symbol(x, Decl(jsxReactTestSuite.tsx, 98, 10))
>y : Symbol(y, Decl(jsxReactTestSuite.tsx, 9, 11))
<x-component />;
@@ -215,24 +215,24 @@ var x =
<Component { ...x } y={2} />;
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
>x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3))
>y : Symbol(unknown)
>y : Symbol(y, Decl(jsxReactTestSuite.tsx, 104, 19))
<Component { ... x } y={2} z />;
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
>x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3))
>y : Symbol(unknown)
>z : Symbol(unknown)
>y : Symbol(y, Decl(jsxReactTestSuite.tsx, 106, 20))
>z : Symbol(z, Decl(jsxReactTestSuite.tsx, 106, 26))
<Component x={1} {...y} />;
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
>x : Symbol(unknown)
>x : Symbol(x, Decl(jsxReactTestSuite.tsx, 108, 10))
>y : Symbol(y, Decl(jsxReactTestSuite.tsx, 9, 11))
<Component x={1} y="2" {...z} {...z}><Child /></Component>;
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
>x : Symbol(unknown)
>y : Symbol(unknown)
>x : Symbol(x, Decl(jsxReactTestSuite.tsx, 111, 10))
>y : Symbol(y, Decl(jsxReactTestSuite.tsx, 111, 16))
>z : Symbol(z, Decl(jsxReactTestSuite.tsx, 11, 11))
>z : Symbol(z, Decl(jsxReactTestSuite.tsx, 11, 11))
>Child : Symbol(Child, Decl(jsxReactTestSuite.tsx, 5, 11))
@@ -240,11 +240,11 @@ var x =
<Component x="1" {...(z = { y: 2 }, z)} z={3}>Text</Component>;
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
>x : Symbol(unknown)
>x : Symbol(x, Decl(jsxReactTestSuite.tsx, 113, 10))
>z : Symbol(z, Decl(jsxReactTestSuite.tsx, 11, 11))
>y : Symbol(y, Decl(jsxReactTestSuite.tsx, 113, 27))
>z : Symbol(z, Decl(jsxReactTestSuite.tsx, 11, 11))
>z : Symbol(unknown)
>z : Symbol(z, Decl(jsxReactTestSuite.tsx, 113, 39))
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
@@ -116,7 +116,7 @@ var x =
>div : any
attr1={
>attr1 : any
>attr1 : string
"foo" + "bar"
>"foo" + "bar" : string
@@ -124,7 +124,7 @@ var x =
>"bar" : "bar"
}
attr2={
>attr2 : any
>attr2 : string
"foo" + "bar" +
>"foo" + "bar" + "baz" + "bug" : string
@@ -138,7 +138,7 @@ var x =
>"bug" : "bug"
}
attr3={
>attr3 : any
>attr3 : string
"foo" + "bar" +
>"foo" + "bar" + "baz" + "bug" : string
@@ -154,7 +154,7 @@ var x =
// Extra line here.
}
attr4="baz">
>attr4 : any
>attr4 : string
</div>;
>div : any
@@ -198,14 +198,14 @@ var x =
/* a multi-line
comment */
attr1="foo">
>attr1 : any
>attr1 : string
<span // a double-slash comment
><span // a double-slash comment attr2="bar" /> : any
>span : any
attr2="bar"
>attr2 : any
>attr2 : string
/>
</div>
@@ -231,7 +231,7 @@ var x =
<Component constructor="foo" />;
><Component constructor="foo" /> : any
>Component : any
>constructor : any
>constructor : string
<Namespace.Component />;
><Namespace.Component /> : any
@@ -251,11 +251,11 @@ var x =
><Component { ... x } y={2 } z /> : any
>Component : any
>x : any
>y : any
>y : number
={2 } z />;
>2 : 2
>z : any
>z : true
<Component
><Component {...this.props} sound="moo" /> : any
@@ -265,7 +265,7 @@ var x =
>this.props : any
>this : any
>props : any
>sound : any
>sound : string
<font-face />;
><font-face /> : any
@@ -290,21 +290,21 @@ var x =
><Component { ...x } y={2} /> : any
>Component : any
>x : any
>y : any
>y : number
>2 : 2
<Component { ... x } y={2} z />;
><Component { ... x } y={2} z /> : any
>Component : any
>x : any
>y : any
>y : number
>2 : 2
>z : any
>z : true
<Component x={1} {...y} />;
><Component x={1} {...y} /> : any
>Component : any
>x : any
>x : number
>1 : 1
>y : any
@@ -312,9 +312,9 @@ var x =
<Component x={1} y="2" {...z} {...z}><Child /></Component>;
><Component x={1} y="2" {...z} {...z}><Child /></Component> : any
>Component : any
>x : any
>x : number
>1 : 1
>y : any
>y : string
>z : any
>z : any
><Child /> : any
@@ -324,7 +324,7 @@ var x =
<Component x="1" {...(z = { y: 2 }, z)} z={3}>Text</Component>;
><Component x="1" {...(z = { y: 2 }, z)} z={3}>Text</Component> : any
>Component : any
>x : any
>x : string
>(z = { y: 2 }, z) : any
>z = { y: 2 }, z : any
>z = { y: 2 } : { y: number; }
@@ -333,7 +333,7 @@ var x =
>y : number
>2 : 2
>z : any
>z : any
>z : number
>3 : 3
>Component : any
@@ -5,17 +5,17 @@ declare var React: any;
<foo class-id/>;
>foo : Symbol(unknown)
>class-id : Symbol(unknown)
>class-id : Symbol(class-id, Decl(keywordInJsxIdentifier.tsx, 2, 4))
<foo class/>;
>foo : Symbol(unknown)
>class : Symbol(unknown)
>class : Symbol(class, Decl(keywordInJsxIdentifier.tsx, 3, 4))
<foo class-id="1"/>;
>foo : Symbol(unknown)
>class-id : Symbol(unknown)
>class-id : Symbol(class-id, Decl(keywordInJsxIdentifier.tsx, 4, 4))
<foo class="1"/>;
>foo : Symbol(unknown)
>class : Symbol(unknown)
>class : Symbol(class, Decl(keywordInJsxIdentifier.tsx, 5, 4))
@@ -6,20 +6,20 @@ declare var React: any;
<foo class-id/>;
><foo class-id/> : any
>foo : any
>class-id : any
>class-id : true
<foo class/>;
><foo class/> : any
>foo : any
>class : any
>class : true
<foo class-id="1"/>;
><foo class-id="1"/> : any
>foo : any
>class-id : any
>class-id : string
<foo class="1"/>;
><foo class="1"/> : any
>foo : any
>class : any
>class : string
@@ -60,6 +60,6 @@ import {layout} from '../../utils/theme'; // <- DO NOT DROP this import
const x = <TabBar height={layout.footerHeight} />;
>x : Symbol(x, Decl(NavigationView.js, 2, 5))
>TabBar : Symbol(TabBar, Decl(NavigationView.js, 0, 6))
>height : Symbol(layout)
>height : Symbol(height, Decl(NavigationView.js, 2, 17))
>layout : Symbol(layout, Decl(NavigationView.js, 1, 8))
@@ -17,5 +17,5 @@ declare var foo: any;
<foo data/>;
>foo : Symbol(unknown)
>data : Symbol(unknown)
>data : Symbol(data, Decl(test.tsx, 3, 4))
@@ -18,5 +18,5 @@ declare var foo: any;
<foo data/>;
><foo data/> : any
>foo : any
>data : any
>data : true
@@ -14,11 +14,11 @@ declare var x: any;
<foo data/>;
>foo : Symbol(unknown)
>data : Symbol(unknown)
>data : Symbol(data, Decl(reactNamespaceJSXEmit.tsx, 6, 4))
<Bar x={x} />;
>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11))
>x : Symbol(unknown)
>x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 7, 4))
>x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11))
<x-component />;
@@ -31,5 +31,5 @@ declare var x: any;
<Bar { ...x } y={2} />;
>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11))
>x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11))
>y : Symbol(unknown)
>y : Symbol(y, Decl(reactNamespaceJSXEmit.tsx, 10, 13))
@@ -15,7 +15,7 @@ declare var x: any;
<foo data/>;
><foo data/> : any
>foo : any
>data : any
>data : true
<Bar x={x} />;
><Bar x={x} /> : any
@@ -36,6 +36,6 @@ declare var x: any;
><Bar { ...x } y={2} /> : any
>Bar : any
>x : any
>y : any
>y : number
>2 : 2
@@ -1,7 +1,12 @@
tests/cases/conformance/jsx/tsxAttributeErrors.tsx(15,6): error TS2322: Type '42' is not assignable to type 'string'.
tests/cases/conformance/jsx/tsxAttributeErrors.tsx(18,6): error TS2322: Type '"foo"' is not assignable to type 'number'.
tests/cases/conformance/jsx/tsxAttributeErrors.tsx(22,6): error TS2606: Property 'text' of JSX spread attribute is not assignable to target property.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/tsxAttributeErrors.tsx(15,6): error TS2322: Type '{ text: 42; }' is not assignable to type '{ text?: string; width?: number; }'.
Types of property 'text' are incompatible.
Type '42' is not assignable to type 'string'.
tests/cases/conformance/jsx/tsxAttributeErrors.tsx(18,6): error TS2322: Type '{ width: "foo"; }' is not assignable to type '{ text?: string; width?: number; }'.
Types of property 'width' are incompatible.
Type '"foo"' is not assignable to type 'number'.
tests/cases/conformance/jsx/tsxAttributeErrors.tsx(22,6): error TS2322: Type '{ text: number; }' is not assignable to type '{ text?: string; width?: number; }'.
Types of property 'text' are incompatible.
Type 'number' is not assignable to type 'string'.
==== tests/cases/conformance/jsx/tsxAttributeErrors.tsx (3 errors) ====
@@ -21,19 +26,24 @@ tests/cases/conformance/jsx/tsxAttributeErrors.tsx(22,6): error TS2606: Property
// Error, number is not assignable to string
<div text={42} />;
~~~~~~~~~
!!! error TS2322: Type '42' is not assignable to type 'string'.
!!! error TS2322: Type '{ text: 42; }' is not assignable to type '{ text?: string; width?: number; }'.
!!! error TS2322: Types of property 'text' are incompatible.
!!! error TS2322: Type '42' is not assignable to type 'string'.
// Error, string is not assignable to number
<div width={'foo'} />;
~~~~~~~~~~~~~
!!! error TS2322: Type '"foo"' is not assignable to type 'number'.
!!! error TS2322: Type '{ width: "foo"; }' is not assignable to type '{ text?: string; width?: number; }'.
!!! error TS2322: Types of property 'width' are incompatible.
!!! error TS2322: Type '"foo"' is not assignable to type 'number'.
// Error, number is not assignable to string
var attribs = { text: 100 };
<div {...attribs} />;
~~~~~~~~~~~~
!!! error TS2606: Property 'text' of JSX spread attribute is not assignable to target property.
!!! error TS2606: Type 'number' is not assignable to type 'string'.
!!! error TS2322: Type '{ text: number; }' is not assignable to type '{ text?: string; width?: number; }'.
!!! error TS2322: Types of property 'text' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
// No errors here
<span foo='bar' bar={'foo'} />;
@@ -1,10 +1,20 @@
tests/cases/conformance/jsx/file.tsx(23,8): error TS2322: Type '"0"' is not assignable to type 'number'.
tests/cases/conformance/jsx/file.tsx(24,8): error TS2339: Property 'y' does not exist on type 'Attribs1'.
tests/cases/conformance/jsx/file.tsx(25,8): error TS2339: Property 'y' does not exist on type 'Attribs1'.
tests/cases/conformance/jsx/file.tsx(26,8): error TS2322: Type '"32"' is not assignable to type 'number'.
tests/cases/conformance/jsx/file.tsx(27,8): error TS2339: Property 'var' does not exist on type 'Attribs1'.
tests/cases/conformance/jsx/file.tsx(29,1): error TS2324: Property 'reqd' is missing in type '{ reqd: string; }'.
tests/cases/conformance/jsx/file.tsx(30,8): error TS2322: Type '10' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(23,8): error TS2322: Type '{ x: "0"; }' is not assignable to type 'Attribs1'.
Types of property 'x' are incompatible.
Type '"0"' is not assignable to type 'number'.
tests/cases/conformance/jsx/file.tsx(24,8): error TS2322: Type '{ y: 0; }' is not assignable to type 'Attribs1'.
Property 'y' does not exist on type 'Attribs1'.
tests/cases/conformance/jsx/file.tsx(25,8): error TS2322: Type '{ y: "foo"; }' is not assignable to type 'Attribs1'.
Property 'y' does not exist on type 'Attribs1'.
tests/cases/conformance/jsx/file.tsx(26,8): error TS2322: Type '{ x: "32"; }' is not assignable to type 'Attribs1'.
Types of property 'x' are incompatible.
Type '"32"' is not assignable to type 'number'.
tests/cases/conformance/jsx/file.tsx(27,8): error TS2322: Type '{ var: "10"; }' is not assignable to type 'Attribs1'.
Property 'var' does not exist on type 'Attribs1'.
tests/cases/conformance/jsx/file.tsx(29,1): error TS2322: Type '{}' is not assignable to type '{ reqd: string; }'.
Property 'reqd' is missing in type '{}'.
tests/cases/conformance/jsx/file.tsx(30,8): error TS2322: Type '{ reqd: 10; }' is not assignable to type '{ reqd: string; }'.
Types of property 'reqd' are incompatible.
Type '10' is not assignable to type 'string'.
==== tests/cases/conformance/jsx/file.tsx (7 errors) ====
@@ -32,26 +42,36 @@ tests/cases/conformance/jsx/file.tsx(30,8): error TS2322: Type '10' is not assig
// Errors
<test1 x={'0'} />; // Error, '0' is not number
~~~~~~~
!!! error TS2322: Type '"0"' is not assignable to type 'number'.
!!! error TS2322: Type '{ x: "0"; }' is not assignable to type 'Attribs1'.
!!! error TS2322: Types of property 'x' are incompatible.
!!! error TS2322: Type '"0"' is not assignable to type 'number'.
<test1 y={0} />; // Error, no property "y"
~
!!! error TS2339: Property 'y' does not exist on type 'Attribs1'.
~~~~~
!!! error TS2322: Type '{ y: 0; }' is not assignable to type 'Attribs1'.
!!! error TS2322: Property 'y' does not exist on type 'Attribs1'.
<test1 y="foo" />; // Error, no property "y"
~
!!! error TS2339: Property 'y' does not exist on type 'Attribs1'.
~~~~~~~
!!! error TS2322: Type '{ y: "foo"; }' is not assignable to type 'Attribs1'.
!!! error TS2322: Property 'y' does not exist on type 'Attribs1'.
<test1 x="32" />; // Error, "32" is not number
~~~~~~
!!! error TS2322: Type '"32"' is not assignable to type 'number'.
!!! error TS2322: Type '{ x: "32"; }' is not assignable to type 'Attribs1'.
!!! error TS2322: Types of property 'x' are incompatible.
!!! error TS2322: Type '"32"' is not assignable to type 'number'.
<test1 var="10" />; // Error, no 'var' property
~~~
!!! error TS2339: Property 'var' does not exist on type 'Attribs1'.
~~~~~~~~
!!! error TS2322: Type '{ var: "10"; }' is not assignable to type 'Attribs1'.
!!! error TS2322: Property 'var' does not exist on type 'Attribs1'.
<test2 />; // Error, missing reqd
~~~~~~~~~
!!! error TS2324: Property 'reqd' is missing in type '{ reqd: string; }'.
!!! error TS2322: Type '{}' is not assignable to type '{ reqd: string; }'.
!!! error TS2322: Property 'reqd' is missing in type '{}'.
<test2 reqd={10} />; // Error, reqd is not string
~~~~~~~~~
!!! error TS2322: Type '10' is not assignable to type 'string'.
!!! error TS2322: Type '{ reqd: 10; }' is not assignable to type '{ reqd: string; }'.
!!! error TS2322: Types of property 'reqd' are incompatible.
!!! error TS2322: Type '10' is not assignable to type 'string'.
// Should be OK
<var var='var' />;
@@ -1,4 +1,6 @@
tests/cases/conformance/jsx/file.tsx(11,14): error TS2322: Type '"world"' is not assignable to type 'boolean'.
tests/cases/conformance/jsx/file.tsx(11,14): error TS2322: Type '{ bar: "world"; }' is not assignable to type '{ [s: string]: boolean; }'.
Property 'bar' is incompatible with index signature.
Type '"world"' is not assignable to type 'boolean'.
==== tests/cases/conformance/jsx/react.d.ts (0 errors) ====
@@ -25,7 +27,9 @@ tests/cases/conformance/jsx/file.tsx(11,14): error TS2322: Type '"world"' is not
// Should be an error
<MyComponent bar='world' />;
~~~~~~~~~~~
!!! error TS2322: Type '"world"' is not assignable to type 'boolean'.
!!! error TS2322: Type '{ bar: "world"; }' is not assignable to type '{ [s: string]: boolean; }'.
!!! error TS2322: Property 'bar' is incompatible with index signature.
!!! error TS2322: Type '"world"' is not assignable to type 'boolean'.
// Should be OK
<MyComponent bar={true} />;
@@ -1,4 +1,5 @@
tests/cases/conformance/jsx/file.tsx(11,22): error TS2339: Property 'bar' does not exist on type 'IntrinsicAttributes & { ref?: string; }'.
tests/cases/conformance/jsx/file.tsx(11,22): error TS2322: Type '{ bar: "world"; }' is not assignable to type 'IntrinsicAttributes & { ref?: string; }'.
Property 'bar' does not exist on type 'IntrinsicAttributes & { ref?: string; }'.
==== tests/cases/conformance/jsx/react.d.ts (0 errors) ====
@@ -27,7 +28,8 @@ tests/cases/conformance/jsx/file.tsx(11,22): error TS2339: Property 'bar' does n
// Should be an OK
var x = <MyComponent bar='world' />;
~~~
!!! error TS2339: Property 'bar' does not exist on type 'IntrinsicAttributes & { ref?: string; }'.
~~~~~~~~~~~
!!! error TS2322: Type '{ bar: "world"; }' is not assignable to type 'IntrinsicAttributes & { ref?: string; }'.
!!! error TS2322: Property 'bar' does not exist on type 'IntrinsicAttributes & { ref?: string; }'.
@@ -1,5 +1,9 @@
tests/cases/conformance/jsx/file.tsx(26,10): error TS2324: Property 'reqd' is missing in type 'IntrinsicAttributes & { reqd: any; }'.
tests/cases/conformance/jsx/file.tsx(29,10): error TS2324: Property 'reqd' is missing in type 'IntrinsicAttributes & { reqd: any; }'.
tests/cases/conformance/jsx/file.tsx(26,10): error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { reqd: any; }'.
Type '{}' is not assignable to type '{ reqd: any; }'.
Property 'reqd' is missing in type '{}'.
tests/cases/conformance/jsx/file.tsx(29,10): error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { reqd: any; }'.
Type '{}' is not assignable to type '{ reqd: any; }'.
Property 'reqd' is missing in type '{}'.
==== tests/cases/conformance/jsx/react.d.ts (0 errors) ====
@@ -44,11 +48,15 @@ tests/cases/conformance/jsx/file.tsx(29,10): error TS2324: Property 'reqd' is mi
const T = TestMod.Test;
var t1 = <T />;
~~~~~
!!! error TS2324: Property 'reqd' is missing in type 'IntrinsicAttributes & { reqd: any; }'.
!!! error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { reqd: any; }'.
!!! error TS2322: Type '{}' is not assignable to type '{ reqd: any; }'.
!!! error TS2322: Property 'reqd' is missing in type '{}'.
// Should error
var t2 = <TestMod.Test />;
~~~~~~~~~~~~~~~~
!!! error TS2324: Property 'reqd' is missing in type 'IntrinsicAttributes & { reqd: any; }'.
!!! error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { reqd: any; }'.
!!! error TS2322: Type '{}' is not assignable to type '{ reqd: any; }'.
!!! error TS2322: Property 'reqd' is missing in type '{}'.
@@ -1,5 +1,9 @@
tests/cases/conformance/jsx/file.tsx(14,28): error TS2322: Type '2' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(16,28): error TS2322: Type 'true' is not assignable to type 'string | number'.
tests/cases/conformance/jsx/file.tsx(14,28): error TS2322: Type '{ primaryText: 2; }' is not assignable to type 'IProps'.
Types of property 'primaryText' are incompatible.
Type '2' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(16,28): error TS2322: Type '{ justRandomProp1: true; primaryText: "hello"; }' is not assignable to type 'IProps'.
Property 'justRandomProp1' is incompatible with index signature.
Type 'true' is not assignable to type 'string | number'.
==== tests/cases/conformance/jsx/react.d.ts (0 errors) ====
@@ -28,11 +32,15 @@ tests/cases/conformance/jsx/file.tsx(16,28): error TS2322: Type 'true' is not as
<div>
<VerticalNavMenuItem primaryText={2} /> // error
~~~~~~~~~~~~~~~
!!! error TS2322: Type '2' is not assignable to type 'string'.
!!! error TS2322: Type '{ primaryText: 2; }' is not assignable to type 'IProps'.
!!! error TS2322: Types of property 'primaryText' are incompatible.
!!! error TS2322: Type '2' is not assignable to type 'string'.
<VerticalNavMenuItem justRandomProp={2} primaryText={"hello"} /> // ok
<VerticalNavMenuItem justRandomProp1={true} primaryText={"hello"} /> // error
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type 'true' is not assignable to type 'string | number'.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ justRandomProp1: true; primaryText: "hello"; }' is not assignable to type 'IProps'.
!!! error TS2322: Property 'justRandomProp1' is incompatible with index signature.
!!! error TS2322: Type 'true' is not assignable to type 'string | number'.
</div>
)
}
@@ -0,0 +1,24 @@
tests/cases/conformance/jsx/file.tsx(12,21): error TS2322: Type '{ prop1: "hello"; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<BigGreeter> & {} & { children?: ReactNode; }'.
Property 'prop1' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<BigGreeter> & {} & { children?: ReactNode; }'.
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
import React = require('react');
class BigGreeter extends React.Component<{ }, {}> {
render() {
return <div>Default hi</div>;
}
greeting: string;
}
// Error
let a = <BigGreeter prop1="hello" />
~~~~~~~~~~~~~
!!! error TS2322: Type '{ prop1: "hello"; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<BigGreeter> & {} & { children?: ReactNode; }'.
!!! error TS2322: Property 'prop1' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<BigGreeter> & {} & { children?: ReactNode; }'.
// OK
let b = <BigGreeter ref={(input) => { this.textInput = input; }} />
let c = <BigGreeter data-extra="hi" />
@@ -0,0 +1,48 @@
//// [file.tsx]
import React = require('react');
class BigGreeter extends React.Component<{ }, {}> {
render() {
return <div>Default hi</div>;
}
greeting: string;
}
// Error
let a = <BigGreeter prop1="hello" />
// OK
let b = <BigGreeter ref={(input) => { this.textInput = input; }} />
let c = <BigGreeter data-extra="hi" />
//// [file.jsx]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var _this = this;
exports.__esModule = true;
var React = require("react");
var BigGreeter = (function (_super) {
__extends(BigGreeter, _super);
function BigGreeter() {
return _super !== null && _super.apply(this, arguments) || this;
}
BigGreeter.prototype.render = function () {
return <div>Default hi</div>;
};
return BigGreeter;
}(React.Component));
// Error
var a = <BigGreeter prop1="hello"/>;
// OK
var b = <BigGreeter ref={function (input) { _this.textInput = input; }}/>;
var c = <BigGreeter data-extra="hi"/>;
@@ -1,9 +1,13 @@
tests/cases/conformance/jsx/file.tsx(19,8): error TS2606: Property 'x' of JSX spread attribute is not assignable to target property.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(23,1): error TS2324: Property 'x' is missing in type 'Attribs1'.
tests/cases/conformance/jsx/file.tsx(31,15): error TS2606: Property 'x' of JSX spread attribute is not assignable to target property.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(39,8): error TS2322: Type '32' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(19,8): error TS2322: Type '{ x: number; }' is not assignable to type 'Attribs1'.
Types of property 'x' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(23,8): error TS2322: Type '{ y: number; }' is not assignable to type 'Attribs1'.
Property 'x' is missing in type '{ y: number; }'.
tests/cases/conformance/jsx/file.tsx(31,8): error TS2322: Type '{ x: number; y: number; }' is not assignable to type 'Attribs1'.
Types of property 'x' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(35,8): error TS2322: Type '{ x: string; y: number; extra: number; }' is not assignable to type 'Attribs1'.
Property 'extra' does not exist on type 'Attribs1'.
==== tests/cases/conformance/jsx/file.tsx (4 errors) ====
@@ -27,14 +31,16 @@ tests/cases/conformance/jsx/file.tsx(39,8): error TS2322: Type '32' is not assig
var obj2 = { x: 32 };
<test1 {...obj2} />
~~~~~~~~~
!!! error TS2606: Property 'x' of JSX spread attribute is not assignable to target property.
!!! error TS2606: Type 'number' is not assignable to type 'string'.
!!! error TS2322: Type '{ x: number; }' is not assignable to type 'Attribs1'.
!!! error TS2322: Types of property 'x' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
// Error, x is missing
var obj3 = { y: 32 };
<test1 {...obj3} />
~~~~~~~~~~~~~~~~~~~
!!! error TS2324: Property 'x' is missing in type 'Attribs1'.
~~~~~~~~~
!!! error TS2322: Type '{ y: number; }' is not assignable to type 'Attribs1'.
!!! error TS2322: Property 'x' is missing in type '{ y: number; }'.
// OK
var obj4 = { x: 32, y: 32 };
@@ -43,17 +49,19 @@ tests/cases/conformance/jsx/file.tsx(39,8): error TS2322: Type '32' is not assig
// Error
var obj5 = { x: 32, y: 32 };
<test1 x="ok" {...obj5} />
~~~~~~~~~
!!! error TS2606: Property 'x' of JSX spread attribute is not assignable to target property.
!!! error TS2606: Type 'number' is not assignable to type 'string'.
// OK
var obj6 = { x: 'ok', y: 32, extra: 100 };
<test1 {...obj6} />
~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ x: number; y: number; }' is not assignable to type 'Attribs1'.
!!! error TS2322: Types of property 'x' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
// Error
var obj6 = { x: 'ok', y: 32, extra: 100 };
<test1 {...obj6} />
~~~~~~~~~
!!! error TS2322: Type '{ x: string; y: number; extra: number; }' is not assignable to type 'Attribs1'.
!!! error TS2322: Property 'extra' does not exist on type 'Attribs1'.
// OK (spread override)
var obj7 = { x: 'foo' };
<test1 x={32} {...obj7} />
~~~~~~
!!! error TS2322: Type '32' is not assignable to type 'string'.
@@ -31,11 +31,11 @@ var obj4 = { x: 32, y: 32 };
var obj5 = { x: 32, y: 32 };
<test1 x="ok" {...obj5} />
// OK
// Error
var obj6 = { x: 'ok', y: 32, extra: 100 };
<test1 {...obj6} />
// Error
// OK (spread override)
var obj7 = { x: 'foo' };
<test1 x={32} {...obj7} />
@@ -56,9 +56,9 @@ var obj4 = { x: 32, y: 32 };
// Error
var obj5 = { x: 32, y: 32 };
<test1 x="ok" {...obj5}/>;
// OK
// Error
var obj6 = { x: 'ok', y: 32, extra: 100 };
<test1 {...obj6}/>;
// Error
// OK (spread override)
var obj7 = { x: 'foo' };
<test1 x={32} {...obj7}/>;
@@ -1,8 +1,8 @@
tests/cases/conformance/jsx/file.tsx(21,16): error TS2606: Property 'x' of JSX spread attribute is not assignable to target property.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(25,9): error TS2324: Property 'x' is missing in type 'Attribs1'.
tests/cases/conformance/jsx/file.tsx(29,1): error TS2324: Property 'x' is missing in type 'Attribs1'.
tests/cases/conformance/jsx/file.tsx(30,1): error TS2324: Property 'toString' is missing in type 'Attribs2'.
tests/cases/conformance/jsx/file.tsx(17,16): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/jsx/file.tsx(21,16): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/jsx/file.tsx(25,16): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/jsx/file.tsx(29,8): error TS2322: Type '{}' is not assignable to type 'Attribs1'.
Property 'x' is missing in type '{}'.
==== tests/cases/conformance/jsx/file.tsx (4 errors) ====
@@ -23,26 +23,26 @@ tests/cases/conformance/jsx/file.tsx(30,1): error TS2324: Property 'toString' is
function make1<T extends {x: string}> (obj: T) {
return <test1 {...obj} />; // OK
~~~~~~~~
!!! error TS2698: Spread types may only be created from object types.
}
function make2<T extends {x: number}> (obj: T) {
return <test1 {...obj} />; // Error (x is number, not string)
~~~~~~~~
!!! error TS2606: Property 'x' of JSX spread attribute is not assignable to target property.
!!! error TS2606: Type 'number' is not assignable to type 'string'.
!!! error TS2698: Spread types may only be created from object types.
}
function make3<T extends {y: string}> (obj: T) {
return <test1 {...obj} />; // Error, missing x
~~~~~~~~~~~~~~~~~~
!!! error TS2324: Property 'x' is missing in type 'Attribs1'.
~~~~~~~~
!!! error TS2698: Spread types may only be created from object types.
}
<test1 {...{}} />; // Error, missing x
~~~~~~~~~~~~~~~~~
!!! error TS2324: Property 'x' is missing in type 'Attribs1'.
~~~~~~~
!!! error TS2322: Type '{}' is not assignable to type 'Attribs1'.
!!! error TS2322: Property 'x' is missing in type '{}'.
<test2 {...{}} />; // Error, missing toString
~~~~~~~~~~~~~~~~~
!!! error TS2324: Property 'toString' is missing in type 'Attribs2'.
@@ -1,6 +1,11 @@
tests/cases/conformance/jsx/file.tsx(10,8): error TS2322: Type 'boolean' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(11,8): error TS2322: Type '"true"' is not assignable to type 'boolean'.
tests/cases/conformance/jsx/file.tsx(12,1): error TS2324: Property 'n' is missing in type '{ n: boolean; }'.
tests/cases/conformance/jsx/file.tsx(10,8): error TS2322: Type '{ s: true; }' is not assignable to type '{ n?: boolean; s?: string; }'.
Types of property 's' are incompatible.
Type 'true' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(11,8): error TS2322: Type '{ n: "true"; }' is not assignable to type '{ n?: boolean; s?: string; }'.
Types of property 'n' are incompatible.
Type '"true"' is not assignable to type 'boolean'.
tests/cases/conformance/jsx/file.tsx(12,1): error TS2322: Type '{}' is not assignable to type '{ n: boolean; }'.
Property 'n' is missing in type '{}'.
==== tests/cases/conformance/jsx/file.tsx (3 errors) ====
@@ -15,13 +20,18 @@ tests/cases/conformance/jsx/file.tsx(12,1): error TS2324: Property 'n' is missin
// Error
<test1 s />;
~
!!! error TS2322: Type 'boolean' is not assignable to type 'string'.
!!! error TS2322: Type '{ s: true; }' is not assignable to type '{ n?: boolean; s?: string; }'.
!!! error TS2322: Types of property 's' are incompatible.
!!! error TS2322: Type 'true' is not assignable to type 'string'.
<test1 n='true' />;
~~~~~~~~
!!! error TS2322: Type '"true"' is not assignable to type 'boolean'.
!!! error TS2322: Type '{ n: "true"; }' is not assignable to type '{ n?: boolean; s?: string; }'.
!!! error TS2322: Types of property 'n' are incompatible.
!!! error TS2322: Type '"true"' is not assignable to type 'boolean'.
<test2 />;
~~~~~~~~~
!!! error TS2324: Property 'n' is missing in type '{ n: boolean; }'.
!!! error TS2322: Type '{}' is not assignable to type '{ n: boolean; }'.
!!! error TS2322: Property 'n' is missing in type '{}'.
// OK
<test1 n />;
@@ -1,4 +1,6 @@
tests/cases/conformance/jsx/file.tsx(9,8): error TS2322: Type '32' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(9,8): error TS2322: Type '{ data-foo: 32; }' is not assignable to type '{ "data-foo"?: string; }'.
Types of property '"data-foo"' are incompatible.
Type '32' is not assignable to type 'string'.
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
@@ -12,7 +14,9 @@ tests/cases/conformance/jsx/file.tsx(9,8): error TS2322: Type '32' is not assign
// Error
<test1 data-foo={32} />;
~~~~~~~~~~~~~
!!! error TS2322: Type '32' is not assignable to type 'string'.
!!! error TS2322: Type '{ data-foo: 32; }' is not assignable to type '{ "data-foo"?: string; }'.
!!! error TS2322: Types of property '"data-foo"' are incompatible.
!!! error TS2322: Type '32' is not assignable to type 'string'.
// OK
<test1 data-foo={'32'} />;
@@ -1,4 +1,6 @@
tests/cases/conformance/jsx/file.tsx(9,14): error TS2322: Type '0' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(9,14): error TS2322: Type '{ foo: 0; }' is not assignable to type '{ foo: string; }'.
Types of property 'foo' are incompatible.
Type '0' is not assignable to type 'string'.
==== tests/cases/conformance/jsx/react.d.ts (0 errors) ====
@@ -27,5 +29,7 @@ tests/cases/conformance/jsx/file.tsx(9,14): error TS2322: Type '0' is not assign
<MyComponent foo="bar" />; // ok
<MyComponent foo={0} />; // should be an error
~~~~~~~
!!! error TS2322: Type '0' is not assignable to type 'string'.
!!! error TS2322: Type '{ foo: 0; }' is not assignable to type '{ foo: string; }'.
!!! error TS2322: Types of property 'foo' are incompatible.
!!! error TS2322: Type '0' is not assignable to type 'string'.
@@ -0,0 +1,42 @@
//// [file.tsx]
import React = require('react');
interface Prop {
x: boolean;
}
class Poisoned extends React.Component<Prop, {}> {
render() {
return <div>Hello</div>;
}
}
// OK
let p = <Poisoned x/>;
//// [file.jsx]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var React = require("react");
var Poisoned = (function (_super) {
__extends(Poisoned, _super);
function Poisoned() {
return _super !== null && _super.apply(this, arguments) || this;
}
Poisoned.prototype.render = function () {
return <div>Hello</div>;
};
return Poisoned;
}(React.Component));
// OK
var p = <Poisoned x/>;
@@ -0,0 +1,33 @@
=== tests/cases/conformance/jsx/file.tsx ===
import React = require('react');
>React : Symbol(React, Decl(file.tsx, 0, 0))
interface Prop {
>Prop : Symbol(Prop, Decl(file.tsx, 1, 32))
x: boolean;
>x : Symbol(Prop.x, Decl(file.tsx, 3, 16))
}
class Poisoned extends React.Component<Prop, {}> {
>Poisoned : Symbol(Poisoned, Decl(file.tsx, 5, 1))
>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55))
>React : Symbol(React, Decl(file.tsx, 0, 0))
>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55))
>Prop : Symbol(Prop, Decl(file.tsx, 1, 32))
render() {
>render : Symbol(Poisoned.render, Decl(file.tsx, 6, 50))
return <div>Hello</div>;
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45))
}
}
// OK
let p = <Poisoned x/>;
>p : Symbol(p, Decl(file.tsx, 13, 3))
>Poisoned : Symbol(Poisoned, Decl(file.tsx, 5, 1))
>x : Symbol(x, Decl(file.tsx, 13, 17))
@@ -0,0 +1,35 @@
=== tests/cases/conformance/jsx/file.tsx ===
import React = require('react');
>React : typeof React
interface Prop {
>Prop : Prop
x: boolean;
>x : boolean
}
class Poisoned extends React.Component<Prop, {}> {
>Poisoned : Poisoned
>React.Component : React.Component<Prop, {}>
>React : typeof React
>Component : typeof React.Component
>Prop : Prop
render() {
>render : () => JSX.Element
return <div>Hello</div>;
><div>Hello</div> : JSX.Element
>div : any
>div : any
}
}
// OK
let p = <Poisoned x/>;
>p : JSX.Element
><Poisoned x/> : JSX.Element
>Poisoned : typeof Poisoned
>x : true
@@ -0,0 +1,42 @@
//// [file.tsx]
import React = require('react');
interface Prop {
x: true;
}
class Poisoned extends React.Component<Prop, {}> {
render() {
return <div>Hello</div>;
}
}
// OK
let p = <Poisoned x/>;
//// [file.jsx]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var React = require("react");
var Poisoned = (function (_super) {
__extends(Poisoned, _super);
function Poisoned() {
return _super !== null && _super.apply(this, arguments) || this;
}
Poisoned.prototype.render = function () {
return <div>Hello</div>;
};
return Poisoned;
}(React.Component));
// OK
var p = <Poisoned x/>;
@@ -0,0 +1,33 @@
=== tests/cases/conformance/jsx/file.tsx ===
import React = require('react');
>React : Symbol(React, Decl(file.tsx, 0, 0))
interface Prop {
>Prop : Symbol(Prop, Decl(file.tsx, 1, 32))
x: true;
>x : Symbol(Prop.x, Decl(file.tsx, 3, 16))
}
class Poisoned extends React.Component<Prop, {}> {
>Poisoned : Symbol(Poisoned, Decl(file.tsx, 5, 1))
>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55))
>React : Symbol(React, Decl(file.tsx, 0, 0))
>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55))
>Prop : Symbol(Prop, Decl(file.tsx, 1, 32))
render() {
>render : Symbol(Poisoned.render, Decl(file.tsx, 6, 50))
return <div>Hello</div>;
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45))
}
}
// OK
let p = <Poisoned x/>;
>p : Symbol(p, Decl(file.tsx, 13, 3))
>Poisoned : Symbol(Poisoned, Decl(file.tsx, 5, 1))
>x : Symbol(x, Decl(file.tsx, 13, 17))
@@ -0,0 +1,36 @@
=== tests/cases/conformance/jsx/file.tsx ===
import React = require('react');
>React : typeof React
interface Prop {
>Prop : Prop
x: true;
>x : true
>true : true
}
class Poisoned extends React.Component<Prop, {}> {
>Poisoned : Poisoned
>React.Component : React.Component<Prop, {}>
>React : typeof React
>Component : typeof React.Component
>Prop : Prop
render() {
>render : () => JSX.Element
return <div>Hello</div>;
><div>Hello</div> : JSX.Element
>div : any
>div : any
}
}
// OK
let p = <Poisoned x/>;
>p : JSX.Element
><Poisoned x/> : JSX.Element
>Poisoned : typeof Poisoned
>x : true
@@ -0,0 +1,26 @@
tests/cases/conformance/jsx/file.tsx(14,19): error TS2322: Type '{ x: true; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Poisoned> & Prop & { children?: ReactNode; }'.
Type '{ x: true; }' is not assignable to type 'Prop'.
Types of property 'x' are incompatible.
Type 'true' is not assignable to type 'false'.
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
import React = require('react');
interface Prop {
x: false;
}
class Poisoned extends React.Component<Prop, {}> {
render() {
return <div>Hello</div>;
}
}
// Error
let p = <Poisoned x/>;
~
!!! error TS2322: Type '{ x: true; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Poisoned> & Prop & { children?: ReactNode; }'.
!!! error TS2322: Type '{ x: true; }' is not assignable to type 'Prop'.
!!! error TS2322: Types of property 'x' are incompatible.
!!! error TS2322: Type 'true' is not assignable to type 'false'.
@@ -0,0 +1,42 @@
//// [file.tsx]
import React = require('react');
interface Prop {
x: false;
}
class Poisoned extends React.Component<Prop, {}> {
render() {
return <div>Hello</div>;
}
}
// Error
let p = <Poisoned x/>;
//// [file.jsx]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var React = require("react");
var Poisoned = (function (_super) {
__extends(Poisoned, _super);
function Poisoned() {
return _super !== null && _super.apply(this, arguments) || this;
}
Poisoned.prototype.render = function () {
return <div>Hello</div>;
};
return Poisoned;
}(React.Component));
// Error
var p = <Poisoned x/>;
@@ -32,7 +32,7 @@ module Dotted {
var a = <foundFirst x="hello" />;
>a : Symbol(a, Decl(tsxElementResolution.tsx, 17, 3))
>foundFirst : Symbol(JSX.IntrinsicElements.foundFirst, Decl(tsxElementResolution.tsx, 2, 30))
>x : Symbol(x, Decl(tsxElementResolution.tsx, 3, 15))
>x : Symbol(x, Decl(tsxElementResolution.tsx, 17, 19))
var b = <string_named />;
>b : Symbol(b, Decl(tsxElementResolution.tsx, 18, 3))
@@ -33,7 +33,7 @@ var a = <foundFirst x="hello" />;
>a : any
><foundFirst x="hello" /> : any
>foundFirst : typeof foundFirst
>x : any
>x : string
var b = <string_named />;
>b : any
@@ -1,4 +1,5 @@
tests/cases/conformance/jsx/file.tsx(17,7): error TS2339: Property 'x' does not exist on type '{ q?: number; }'.
tests/cases/conformance/jsx/file.tsx(17,7): error TS2322: Type '{ x: 10; }' is not assignable to type '{ q?: number; }'.
Property 'x' does not exist on type '{ q?: number; }'.
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
@@ -19,8 +20,9 @@ tests/cases/conformance/jsx/file.tsx(17,7): error TS2339: Property 'x' does not
}
var Obj2: Obj2type;
<Obj2 x={10} />; // Error
~
!!! error TS2339: Property 'x' does not exist on type '{ q?: number; }'.
~~~~~~
!!! error TS2322: Type '{ x: 10; }' is not assignable to type '{ q?: number; }'.
!!! error TS2322: Property 'x' does not exist on type '{ q?: number; }'.
interface Obj3type {
new(n: string): { x: number; };
@@ -1,6 +1,8 @@
tests/cases/conformance/jsx/file.tsx(17,2): error TS2304: Cannot find name 'Obj2'.
tests/cases/conformance/jsx/file.tsx(23,1): error TS2607: JSX element class does not support attributes because it does not have a 'pr' property
tests/cases/conformance/jsx/file.tsx(30,7): error TS2322: Type '"10"' is not assignable to type 'number'.
tests/cases/conformance/jsx/file.tsx(25,1): error TS2607: JSX element class does not support attributes because it does not have a 'pr' property
tests/cases/conformance/jsx/file.tsx(33,7): error TS2322: Type '{ x: "10"; }' is not assignable to type '{ x: number; }'.
Types of property 'x' are incompatible.
Type '"10"' is not assignable to type 'number'.
==== tests/cases/conformance/jsx/file.tsx (3 errors) ====
@@ -19,10 +21,8 @@ tests/cases/conformance/jsx/file.tsx(30,7): error TS2322: Type '"10"' is not ass
interface Obj2type {
new(n: string): { q?: number; pr: any };
}
var obj2: Obj2type;
var Obj2: Obj2type;
<Obj2 x={10} />; // OK
~~~~
!!! error TS2304: Cannot find name 'Obj2'.
interface Obj3type {
new(n: string): { x: number; };
@@ -31,6 +31,11 @@ tests/cases/conformance/jsx/file.tsx(30,7): error TS2322: Type '"10"' is not ass
<Obj3 x={10} />; // Error
~~~~~~~~~~~~~~~
!!! error TS2607: JSX element class does not support attributes because it does not have a 'pr' property
var attributes: any;
<Obj3 {...attributes} />; // Error
~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2607: JSX element class does not support attributes because it does not have a 'pr' property
<Obj3 {...{}} />; // OK
interface Obj4type {
new(n: string): { x: number; pr: { x: number; } };
@@ -39,5 +44,7 @@ tests/cases/conformance/jsx/file.tsx(30,7): error TS2322: Type '"10"' is not ass
<Obj4 x={10} />; // OK
<Obj4 x={'10'} />; // Error
~~~~~~~~
!!! error TS2322: Type '"10"' is not assignable to type 'number'.
!!! error TS2322: Type '{ x: "10"; }' is not assignable to type '{ x: number; }'.
!!! error TS2322: Types of property 'x' are incompatible.
!!! error TS2322: Type '"10"' is not assignable to type 'number'.
@@ -14,7 +14,7 @@ var Obj1: Obj1type;
interface Obj2type {
new(n: string): { q?: number; pr: any };
}
var obj2: Obj2type;
var Obj2: Obj2type;
<Obj2 x={10} />; // OK
interface Obj3type {
@@ -22,6 +22,9 @@ interface Obj3type {
}
var Obj3: Obj3type;
<Obj3 x={10} />; // Error
var attributes: any;
<Obj3 {...attributes} />; // Error
<Obj3 {...{}} />; // OK
interface Obj4type {
new(n: string): { x: number; pr: { x: number; } };
@@ -34,10 +37,13 @@ var Obj4: Obj4type;
//// [file.jsx]
var Obj1;
<Obj1 x={10}/>; // OK
var obj2;
var Obj2;
<Obj2 x={10}/>; // OK
var Obj3;
<Obj3 x={10}/>; // Error
var attributes;
<Obj3 {...attributes}/>; // Error
<Obj3 {...{}}/>; // OK
var Obj4;
<Obj4 x={10}/>; // OK
<Obj4 x={'10'}/>; // Error
@@ -23,5 +23,5 @@ var obj1: Obj1;
<obj1 x={10} />; // Error
>obj1 : Symbol(unknown)
>x : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 9, 5))
@@ -24,6 +24,6 @@ var obj1: Obj1;
<obj1 x={10} />; // Error
><obj1 x={10} /> : JSX.Element
>obj1 : Obj1
>x : any
>x : number
>10 : 10
@@ -18,5 +18,5 @@ var obj1: Obj1;
<obj1 x={10} />; // OK
>obj1 : Symbol(unknown)
>x : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 8, 5))
@@ -19,6 +19,6 @@ var obj1: Obj1;
<obj1 x={10} />; // OK
><obj1 x={10} /> : JSX.Element
>obj1 : Obj1
>x : any
>x : number
>10 : 10
@@ -1,8 +1,8 @@
tests/cases/conformance/jsx/file.tsx(12,1): error TS2324: Property 'n' is missing in type '{ n: string; }'.
tests/cases/conformance/jsx/file.tsx(12,7): error TS2339: Property 'w' does not exist on type '{ n: string; }'.
tests/cases/conformance/jsx/file.tsx(12,7): error TS2322: Type '{ w: "err"; }' is not assignable to type '{ n: string; }'.
Property 'w' does not exist on type '{ n: string; }'.
==== tests/cases/conformance/jsx/file.tsx (2 errors) ====
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
declare module JSX {
interface Element { }
interface IntrinsicElements {
@@ -15,7 +15,6 @@ tests/cases/conformance/jsx/file.tsx(12,7): error TS2339: Property 'w' does not
// Error
<span w='err' />;
~~~~~~~~~~~~~~~~
!!! error TS2324: Property 'n' is missing in type '{ n: string; }'.
~
!!! error TS2339: Property 'w' does not exist on type '{ n: string; }'.
~~~~~~~
!!! error TS2322: Type '{ w: "err"; }' is not assignable to type '{ n: string; }'.
!!! error TS2322: Property 'w' does not exist on type '{ n: string; }'.
@@ -1,8 +1,8 @@
tests/cases/conformance/jsx/file.tsx(16,1): error TS2324: Property 'm' is missing in type '{ m: string; }'.
tests/cases/conformance/jsx/file.tsx(16,7): error TS2339: Property 'q' does not exist on type '{ m: string; }'.
tests/cases/conformance/jsx/file.tsx(16,7): error TS2322: Type '{ q: ""; }' is not assignable to type '{ m: string; }'.
Property 'q' does not exist on type '{ m: string; }'.
==== tests/cases/conformance/jsx/file.tsx (2 errors) ====
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
declare module JSX {
interface Element { }
interface IntrinsicElements {
@@ -19,8 +19,7 @@ tests/cases/conformance/jsx/file.tsx(16,7): error TS2339: Property 'q' does not
// Error
<span q='' />;
~~~~~~~~~~~~~
!!! error TS2324: Property 'm' is missing in type '{ m: string; }'.
~
!!! error TS2339: Property 'q' does not exist on type '{ m: string; }'.
~~~~
!!! error TS2322: Type '{ q: ""; }' is not assignable to type '{ m: string; }'.
!!! error TS2322: Property 'q' does not exist on type '{ m: string; }'.
@@ -9,5 +9,5 @@ declare module JSX {
// OK, but implicit any
<div n='x' />;
>div : Symbol(unknown)
>n : Symbol(unknown)
>n : Symbol(n, Decl(file1.tsx, 5, 4))
@@ -10,5 +10,5 @@ declare module JSX {
<div n='x' />;
><div n='x' /> : JSX.Element
>div : any
>n : any
>n : string
@@ -64,5 +64,5 @@ var Obj3: Obj3;
<Obj3 x={42} />; // OK
>Obj3 : Symbol(Obj3, Decl(file.tsx, 17, 9), Decl(file.tsx, 23, 3))
>x : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 24, 5))
@@ -67,6 +67,6 @@ var Obj3: Obj3;
<Obj3 x={42} />; // OK
><Obj3 x={42} /> : JSX.Element
>Obj3 : Obj3
>x : any
>x : number
>42 : 42
+17 -17
View File
@@ -23,37 +23,37 @@ var selfClosed1 = <div />;
var selfClosed2 = <div x="1" />;
>selfClosed2 : Symbol(selfClosed2, Decl(file.tsx, 9, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 9, 22))
var selfClosed3 = <div x='1' />;
>selfClosed3 : Symbol(selfClosed3, Decl(file.tsx, 10, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 10, 22))
var selfClosed4 = <div x="1" y='0' />;
>selfClosed4 : Symbol(selfClosed4, Decl(file.tsx, 11, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>y : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 11, 22))
>y : Symbol(y, Decl(file.tsx, 11, 28))
var selfClosed5 = <div x={0} y='0' />;
>selfClosed5 : Symbol(selfClosed5, Decl(file.tsx, 12, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>y : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 12, 22))
>y : Symbol(y, Decl(file.tsx, 12, 28))
var selfClosed6 = <div x={"1"} y='0' />;
>selfClosed6 : Symbol(selfClosed6, Decl(file.tsx, 13, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>y : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 13, 22))
>y : Symbol(y, Decl(file.tsx, 13, 30))
var selfClosed7 = <div x={p} y='p' />;
>selfClosed7 : Symbol(selfClosed7, Decl(file.tsx, 14, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 14, 22))
>p : Symbol(p, Decl(file.tsx, 7, 3))
>y : Symbol(unknown)
>y : Symbol(y, Decl(file.tsx, 14, 28))
var openClosed1 = <div></div>;
>openClosed1 : Symbol(openClosed1, Decl(file.tsx, 16, 3))
@@ -63,20 +63,20 @@ var openClosed1 = <div></div>;
var openClosed2 = <div n='m'>foo</div>;
>openClosed2 : Symbol(openClosed2, Decl(file.tsx, 17, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>n : Symbol(unknown)
>n : Symbol(n, Decl(file.tsx, 17, 22))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var openClosed3 = <div n='m'>{p}</div>;
>openClosed3 : Symbol(openClosed3, Decl(file.tsx, 18, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>n : Symbol(unknown)
>n : Symbol(n, Decl(file.tsx, 18, 22))
>p : Symbol(p, Decl(file.tsx, 7, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var openClosed4 = <div n='m'>{p < p}</div>;
>openClosed4 : Symbol(openClosed4, Decl(file.tsx, 19, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>n : Symbol(unknown)
>n : Symbol(n, Decl(file.tsx, 19, 22))
>p : Symbol(p, Decl(file.tsx, 7, 3))
>p : Symbol(p, Decl(file.tsx, 7, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
@@ -84,7 +84,7 @@ var openClosed4 = <div n='m'>{p < p}</div>;
var openClosed5 = <div n='m'>{p > p}</div>;
>openClosed5 : Symbol(openClosed5, Decl(file.tsx, 20, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>n : Symbol(unknown)
>n : Symbol(n, Decl(file.tsx, 20, 22))
>p : Symbol(p, Decl(file.tsx, 7, 3))
>p : Symbol(p, Decl(file.tsx, 7, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
@@ -118,14 +118,14 @@ class SomeClass {
var rewrites4 = <div a={() => this}></div>;
>rewrites4 : Symbol(rewrites4, Decl(file.tsx, 28, 5))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>a : Symbol(unknown)
>a : Symbol(a, Decl(file.tsx, 28, 22))
>this : Symbol(SomeClass, Decl(file.tsx, 20, 43))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var rewrites5 = <div a={[p, ...p, p]}></div>;
>rewrites5 : Symbol(rewrites5, Decl(file.tsx, 29, 5))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>a : Symbol(unknown)
>a : Symbol(a, Decl(file.tsx, 29, 22))
>p : Symbol(p, Decl(file.tsx, 7, 3))
>p : Symbol(p, Decl(file.tsx, 7, 3))
>p : Symbol(p, Decl(file.tsx, 7, 3))
@@ -134,7 +134,7 @@ class SomeClass {
var rewrites6 = <div a={{p}}></div>;
>rewrites6 : Symbol(rewrites6, Decl(file.tsx, 30, 5))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>a : Symbol(unknown)
>a : Symbol(a, Decl(file.tsx, 30, 22))
>p : Symbol(p, Decl(file.tsx, 30, 27))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
}
+16 -16
View File
@@ -25,36 +25,36 @@ var selfClosed2 = <div x="1" />;
>selfClosed2 : JSX.Element
><div x="1" /> : JSX.Element
>div : any
>x : any
>x : string
var selfClosed3 = <div x='1' />;
>selfClosed3 : JSX.Element
><div x='1' /> : JSX.Element
>div : any
>x : any
>x : string
var selfClosed4 = <div x="1" y='0' />;
>selfClosed4 : JSX.Element
><div x="1" y='0' /> : JSX.Element
>div : any
>x : any
>y : any
>x : string
>y : string
var selfClosed5 = <div x={0} y='0' />;
>selfClosed5 : JSX.Element
><div x={0} y='0' /> : JSX.Element
>div : any
>x : any
>x : number
>0 : 0
>y : any
>y : string
var selfClosed6 = <div x={"1"} y='0' />;
>selfClosed6 : JSX.Element
><div x={"1"} y='0' /> : JSX.Element
>div : any
>x : any
>x : string
>"1" : "1"
>y : any
>y : string
var selfClosed7 = <div x={p} y='p' />;
>selfClosed7 : JSX.Element
@@ -62,7 +62,7 @@ var selfClosed7 = <div x={p} y='p' />;
>div : any
>x : any
>p : any
>y : any
>y : string
var openClosed1 = <div></div>;
>openClosed1 : JSX.Element
@@ -74,14 +74,14 @@ var openClosed2 = <div n='m'>foo</div>;
>openClosed2 : JSX.Element
><div n='m'>foo</div> : JSX.Element
>div : any
>n : any
>n : string
>div : any
var openClosed3 = <div n='m'>{p}</div>;
>openClosed3 : JSX.Element
><div n='m'>{p}</div> : JSX.Element
>div : any
>n : any
>n : string
>p : any
>div : any
@@ -89,7 +89,7 @@ var openClosed4 = <div n='m'>{p < p}</div>;
>openClosed4 : JSX.Element
><div n='m'>{p < p}</div> : JSX.Element
>div : any
>n : any
>n : string
>p < p : boolean
>p : any
>p : any
@@ -99,7 +99,7 @@ var openClosed5 = <div n='m'>{p > p}</div>;
>openClosed5 : JSX.Element
><div n='m'>{p > p}</div> : JSX.Element
>div : any
>n : any
>n : string
>p > p : boolean
>p : any
>p : any
@@ -142,7 +142,7 @@ class SomeClass {
>rewrites4 : JSX.Element
><div a={() => this}></div> : JSX.Element
>div : any
>a : any
>a : () => this
>() => this : () => this
>this : this
>div : any
@@ -151,7 +151,7 @@ class SomeClass {
>rewrites5 : JSX.Element
><div a={[p, ...p, p]}></div> : JSX.Element
>div : any
>a : any
>a : any[]
>[p, ...p, p] : any[]
>p : any
>...p : any
@@ -163,7 +163,7 @@ class SomeClass {
>rewrites6 : JSX.Element
><div a={{p}}></div> : JSX.Element
>div : any
>a : any
>a : { p: any; }
>{p} : { p: any; }
>p : any
>div : any
+1 -1
View File
@@ -6,7 +6,7 @@ declare module JSX {
}
}
var p1, p2, p3;
var p1: any, p2: any, p3: any;
var spreads1 = <div {...p1}>{p2}</div>;
var spreads2 = <div {...p1}>{p2}</div>;
var spreads3 = <div x={p3} {...p1}>{p2}</div>;
+16 -16
View File
@@ -13,51 +13,51 @@ declare module JSX {
}
}
var p1, p2, p3;
var p1: any, p2: any, p3: any;
>p1 : Symbol(p1, Decl(file.tsx, 7, 3))
>p2 : Symbol(p2, Decl(file.tsx, 7, 7))
>p3 : Symbol(p3, Decl(file.tsx, 7, 11))
>p2 : Symbol(p2, Decl(file.tsx, 7, 12))
>p3 : Symbol(p3, Decl(file.tsx, 7, 21))
var spreads1 = <div {...p1}>{p2}</div>;
>spreads1 : Symbol(spreads1, Decl(file.tsx, 8, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>p1 : Symbol(p1, Decl(file.tsx, 7, 3))
>p2 : Symbol(p2, Decl(file.tsx, 7, 7))
>p2 : Symbol(p2, Decl(file.tsx, 7, 12))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var spreads2 = <div {...p1}>{p2}</div>;
>spreads2 : Symbol(spreads2, Decl(file.tsx, 9, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>p1 : Symbol(p1, Decl(file.tsx, 7, 3))
>p2 : Symbol(p2, Decl(file.tsx, 7, 7))
>p2 : Symbol(p2, Decl(file.tsx, 7, 12))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var spreads3 = <div x={p3} {...p1}>{p2}</div>;
>spreads3 : Symbol(spreads3, Decl(file.tsx, 10, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>p3 : Symbol(p3, Decl(file.tsx, 7, 11))
>x : Symbol(x, Decl(file.tsx, 10, 19))
>p3 : Symbol(p3, Decl(file.tsx, 7, 21))
>p1 : Symbol(p1, Decl(file.tsx, 7, 3))
>p2 : Symbol(p2, Decl(file.tsx, 7, 7))
>p2 : Symbol(p2, Decl(file.tsx, 7, 12))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var spreads4 = <div {...p1} x={p3} >{p2}</div>;
>spreads4 : Symbol(spreads4, Decl(file.tsx, 11, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>p1 : Symbol(p1, Decl(file.tsx, 7, 3))
>x : Symbol(unknown)
>p3 : Symbol(p3, Decl(file.tsx, 7, 11))
>p2 : Symbol(p2, Decl(file.tsx, 7, 7))
>x : Symbol(x, Decl(file.tsx, 11, 27))
>p3 : Symbol(p3, Decl(file.tsx, 7, 21))
>p2 : Symbol(p2, Decl(file.tsx, 7, 12))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var spreads5 = <div x={p2} {...p1} y={p3}>{p2}</div>;
>spreads5 : Symbol(spreads5, Decl(file.tsx, 12, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>p2 : Symbol(p2, Decl(file.tsx, 7, 7))
>x : Symbol(x, Decl(file.tsx, 12, 19))
>p2 : Symbol(p2, Decl(file.tsx, 7, 12))
>p1 : Symbol(p1, Decl(file.tsx, 7, 3))
>y : Symbol(unknown)
>p3 : Symbol(p3, Decl(file.tsx, 7, 11))
>p2 : Symbol(p2, Decl(file.tsx, 7, 7))
>y : Symbol(y, Decl(file.tsx, 12, 34))
>p3 : Symbol(p3, Decl(file.tsx, 7, 21))
>p2 : Symbol(p2, Decl(file.tsx, 7, 12))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
+1 -1
View File
@@ -13,7 +13,7 @@ declare module JSX {
}
}
var p1, p2, p3;
var p1: any, p2: any, p3: any;
>p1 : any
>p2 : any
>p3 : any
@@ -19,7 +19,7 @@ declare var Foo, React;
// Should see mod_1['default'] in emit here
<Foo handler={Main}></Foo>;
>Foo : Symbol(Foo, Decl(app.tsx, 1, 11))
>handler : Symbol(unknown)
>handler : Symbol(handler, Decl(app.tsx, 3, 4))
>Main : Symbol(Main, Decl(app.tsx, 0, 6))
>Foo : Symbol(Foo, Decl(app.tsx, 1, 11))
@@ -44,7 +44,7 @@ x3();
var x4 = <T extends={true}>() => {}</T>;
>x4 : Symbol(x4, Decl(file.tsx, 19, 3))
>T : Symbol(T, Decl(file.tsx, 4, 3))
>extends : Symbol(unknown)
>extends : Symbol(extends, Decl(file.tsx, 19, 11))
>T : Symbol(T, Decl(file.tsx, 4, 3))
x4.isElement;
@@ -56,7 +56,7 @@ x4.isElement;
var x5 = <T extends>() => {}</T>;
>x5 : Symbol(x5, Decl(file.tsx, 23, 3))
>T : Symbol(T, Decl(file.tsx, 4, 3))
>extends : Symbol(unknown)
>extends : Symbol(extends, Decl(file.tsx, 23, 11))
>T : Symbol(T, Decl(file.tsx, 4, 3))
x5.isElement;
@@ -50,7 +50,7 @@ var x4 = <T extends={true}>() => {}</T>;
>x4 : JSX.Element
><T extends={true}>() => {}</T> : JSX.Element
>T : any
>extends : any
>extends : boolean
>true : true
>T : any
@@ -64,7 +64,7 @@ var x5 = <T extends>() => {}</T>;
>x5 : JSX.Element
><T extends>() => {}</T> : JSX.Element
>T : any
>extends : any
>extends : true
>T : any
x5.isElement;
@@ -23,7 +23,7 @@ declare namespace JSX {
<div>{() => <div text="wat" />}</div>;
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
>text : Symbol(text, Decl(tsxInArrowFunction.tsx, 4, 14))
>text : Symbol(text, Decl(tsxInArrowFunction.tsx, 12, 16))
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
// didn't work
@@ -31,21 +31,21 @@ declare namespace JSX {
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
>x : Symbol(x, Decl(tsxInArrowFunction.tsx, 15, 6))
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
>text : Symbol(text, Decl(tsxInArrowFunction.tsx, 4, 14))
>text : Symbol(text, Decl(tsxInArrowFunction.tsx, 15, 15))
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
// worked
<div>{() => (<div text="wat" />)}</div>;
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
>text : Symbol(text, Decl(tsxInArrowFunction.tsx, 4, 14))
>text : Symbol(text, Decl(tsxInArrowFunction.tsx, 18, 17))
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
// worked (!)
<div>{() => <div text="wat"></div>}</div>;
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
>text : Symbol(text, Decl(tsxInArrowFunction.tsx, 4, 14))
>text : Symbol(text, Decl(tsxInArrowFunction.tsx, 21, 16))
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
>div : Symbol(JSX.IntrinsicElements.div, Decl(tsxInArrowFunction.tsx, 3, 33))
@@ -26,7 +26,7 @@ declare namespace JSX {
>() => <div text="wat" /> : () => JSX.Element
><div text="wat" /> : JSX.Element
>div : any
>text : any
>text : string
>div : any
// didn't work
@@ -37,7 +37,7 @@ declare namespace JSX {
>x : any
><div text="wat" /> : JSX.Element
>div : any
>text : any
>text : string
>div : any
// worked
@@ -48,7 +48,7 @@ declare namespace JSX {
>(<div text="wat" />) : JSX.Element
><div text="wat" /> : JSX.Element
>div : any
>text : any
>text : string
>div : any
// worked (!)
@@ -58,7 +58,7 @@ declare namespace JSX {
>() => <div text="wat"></div> : () => JSX.Element
><div text="wat"></div> : JSX.Element
>div : any
>text : any
>text : string
>div : any
>div : any
+19 -19
View File
@@ -25,38 +25,38 @@ var selfClosed1 = <div />;
var selfClosed2 = <div x="1" />;
>selfClosed2 : Symbol(selfClosed2, Decl(file.tsx, 10, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 10, 22))
var selfClosed3 = <div x='1' />;
>selfClosed3 : Symbol(selfClosed3, Decl(file.tsx, 11, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 11, 22))
var selfClosed4 = <div x="1" y='0' />;
>selfClosed4 : Symbol(selfClosed4, Decl(file.tsx, 12, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>y : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 12, 22))
>y : Symbol(y, Decl(file.tsx, 12, 28))
var selfClosed5 = <div x={0} y='0' />;
>selfClosed5 : Symbol(selfClosed5, Decl(file.tsx, 13, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>y : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 13, 22))
>y : Symbol(y, Decl(file.tsx, 13, 28))
var selfClosed6 = <div x={"1"} y='0' />;
>selfClosed6 : Symbol(selfClosed6, Decl(file.tsx, 14, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>y : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 14, 22))
>y : Symbol(y, Decl(file.tsx, 14, 30))
var selfClosed7 = <div x={p} y='p' b />;
>selfClosed7 : Symbol(selfClosed7, Decl(file.tsx, 15, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>x : Symbol(x, Decl(file.tsx, 15, 22))
>p : Symbol(p, Decl(file.tsx, 8, 3))
>y : Symbol(unknown)
>b : Symbol(unknown)
>y : Symbol(y, Decl(file.tsx, 15, 28))
>b : Symbol(b, Decl(file.tsx, 15, 34))
var openClosed1 = <div></div>;
>openClosed1 : Symbol(openClosed1, Decl(file.tsx, 17, 3))
@@ -66,20 +66,20 @@ var openClosed1 = <div></div>;
var openClosed2 = <div n='m'>foo</div>;
>openClosed2 : Symbol(openClosed2, Decl(file.tsx, 18, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>n : Symbol(unknown)
>n : Symbol(n, Decl(file.tsx, 18, 22))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var openClosed3 = <div n='m'>{p}</div>;
>openClosed3 : Symbol(openClosed3, Decl(file.tsx, 19, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>n : Symbol(unknown)
>n : Symbol(n, Decl(file.tsx, 19, 22))
>p : Symbol(p, Decl(file.tsx, 8, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var openClosed4 = <div n='m'>{p < p}</div>;
>openClosed4 : Symbol(openClosed4, Decl(file.tsx, 20, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>n : Symbol(unknown)
>n : Symbol(n, Decl(file.tsx, 20, 22))
>p : Symbol(p, Decl(file.tsx, 8, 3))
>p : Symbol(p, Decl(file.tsx, 8, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
@@ -87,8 +87,8 @@ var openClosed4 = <div n='m'>{p < p}</div>;
var openClosed5 = <div n='m' b>{p > p}</div>;
>openClosed5 : Symbol(openClosed5, Decl(file.tsx, 21, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>n : Symbol(unknown)
>b : Symbol(unknown)
>n : Symbol(n, Decl(file.tsx, 21, 22))
>b : Symbol(b, Decl(file.tsx, 21, 28))
>p : Symbol(p, Decl(file.tsx, 8, 3))
>p : Symbol(p, Decl(file.tsx, 8, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
@@ -122,14 +122,14 @@ class SomeClass {
var rewrites4 = <div a={() => this}></div>;
>rewrites4 : Symbol(rewrites4, Decl(file.tsx, 29, 5))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>a : Symbol(unknown)
>a : Symbol(a, Decl(file.tsx, 29, 22))
>this : Symbol(SomeClass, Decl(file.tsx, 21, 45))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var rewrites5 = <div a={[p, ...p, p]}></div>;
>rewrites5 : Symbol(rewrites5, Decl(file.tsx, 30, 5))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>a : Symbol(unknown)
>a : Symbol(a, Decl(file.tsx, 30, 22))
>p : Symbol(p, Decl(file.tsx, 8, 3))
>p : Symbol(p, Decl(file.tsx, 8, 3))
>p : Symbol(p, Decl(file.tsx, 8, 3))
@@ -138,7 +138,7 @@ class SomeClass {
var rewrites6 = <div a={{p}}></div>;
>rewrites6 : Symbol(rewrites6, Decl(file.tsx, 31, 5))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>a : Symbol(unknown)
>a : Symbol(a, Decl(file.tsx, 31, 22))
>p : Symbol(p, Decl(file.tsx, 31, 27))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
}
+18 -18
View File
@@ -27,36 +27,36 @@ var selfClosed2 = <div x="1" />;
>selfClosed2 : JSX.Element
><div x="1" /> : JSX.Element
>div : any
>x : any
>x : string
var selfClosed3 = <div x='1' />;
>selfClosed3 : JSX.Element
><div x='1' /> : JSX.Element
>div : any
>x : any
>x : string
var selfClosed4 = <div x="1" y='0' />;
>selfClosed4 : JSX.Element
><div x="1" y='0' /> : JSX.Element
>div : any
>x : any
>y : any
>x : string
>y : string
var selfClosed5 = <div x={0} y='0' />;
>selfClosed5 : JSX.Element
><div x={0} y='0' /> : JSX.Element
>div : any
>x : any
>x : number
>0 : 0
>y : any
>y : string
var selfClosed6 = <div x={"1"} y='0' />;
>selfClosed6 : JSX.Element
><div x={"1"} y='0' /> : JSX.Element
>div : any
>x : any
>x : string
>"1" : "1"
>y : any
>y : string
var selfClosed7 = <div x={p} y='p' b />;
>selfClosed7 : JSX.Element
@@ -64,8 +64,8 @@ var selfClosed7 = <div x={p} y='p' b />;
>div : any
>x : any
>p : any
>y : any
>b : any
>y : string
>b : true
var openClosed1 = <div></div>;
>openClosed1 : JSX.Element
@@ -77,14 +77,14 @@ var openClosed2 = <div n='m'>foo</div>;
>openClosed2 : JSX.Element
><div n='m'>foo</div> : JSX.Element
>div : any
>n : any
>n : string
>div : any
var openClosed3 = <div n='m'>{p}</div>;
>openClosed3 : JSX.Element
><div n='m'>{p}</div> : JSX.Element
>div : any
>n : any
>n : string
>p : any
>div : any
@@ -92,7 +92,7 @@ var openClosed4 = <div n='m'>{p < p}</div>;
>openClosed4 : JSX.Element
><div n='m'>{p < p}</div> : JSX.Element
>div : any
>n : any
>n : string
>p < p : boolean
>p : any
>p : any
@@ -102,8 +102,8 @@ var openClosed5 = <div n='m' b>{p > p}</div>;
>openClosed5 : JSX.Element
><div n='m' b>{p > p}</div> : JSX.Element
>div : any
>n : any
>b : any
>n : string
>b : true
>p > p : boolean
>p : any
>p : any
@@ -146,7 +146,7 @@ class SomeClass {
>rewrites4 : JSX.Element
><div a={() => this}></div> : JSX.Element
>div : any
>a : any
>a : () => this
>() => this : () => this
>this : this
>div : any
@@ -155,7 +155,7 @@ class SomeClass {
>rewrites5 : JSX.Element
><div a={[p, ...p, p]}></div> : JSX.Element
>div : any
>a : any
>a : any[]
>[p, ...p, p] : any[]
>p : any
>...p : any
@@ -167,7 +167,7 @@ class SomeClass {
>rewrites6 : JSX.Element
><div a={{p}}></div> : JSX.Element
>div : any
>a : any
>a : { p: any; }
>{p} : { p: any; }
>p : any
>div : any
+1 -1
View File
@@ -7,7 +7,7 @@ declare module JSX {
}
declare var React: any;
var p1, p2, p3;
var p1: any, p2: any, p3: any;
var spreads1 = <div {...p1}>{p2}</div>;
var spreads2 = <div {...p1}>{p2}</div>;
var spreads3 = <div x={p3} {...p1}>{p2}</div>;
+16 -16
View File
@@ -15,51 +15,51 @@ declare module JSX {
declare var React: any;
>React : Symbol(React, Decl(file.tsx, 6, 11))
var p1, p2, p3;
var p1: any, p2: any, p3: any;
>p1 : Symbol(p1, Decl(file.tsx, 8, 3))
>p2 : Symbol(p2, Decl(file.tsx, 8, 7))
>p3 : Symbol(p3, Decl(file.tsx, 8, 11))
>p2 : Symbol(p2, Decl(file.tsx, 8, 12))
>p3 : Symbol(p3, Decl(file.tsx, 8, 21))
var spreads1 = <div {...p1}>{p2}</div>;
>spreads1 : Symbol(spreads1, Decl(file.tsx, 9, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>p1 : Symbol(p1, Decl(file.tsx, 8, 3))
>p2 : Symbol(p2, Decl(file.tsx, 8, 7))
>p2 : Symbol(p2, Decl(file.tsx, 8, 12))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var spreads2 = <div {...p1}>{p2}</div>;
>spreads2 : Symbol(spreads2, Decl(file.tsx, 10, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>p1 : Symbol(p1, Decl(file.tsx, 8, 3))
>p2 : Symbol(p2, Decl(file.tsx, 8, 7))
>p2 : Symbol(p2, Decl(file.tsx, 8, 12))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var spreads3 = <div x={p3} {...p1}>{p2}</div>;
>spreads3 : Symbol(spreads3, Decl(file.tsx, 11, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>p3 : Symbol(p3, Decl(file.tsx, 8, 11))
>x : Symbol(x, Decl(file.tsx, 11, 19))
>p3 : Symbol(p3, Decl(file.tsx, 8, 21))
>p1 : Symbol(p1, Decl(file.tsx, 8, 3))
>p2 : Symbol(p2, Decl(file.tsx, 8, 7))
>p2 : Symbol(p2, Decl(file.tsx, 8, 12))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var spreads4 = <div {...p1} x={p3} >{p2}</div>;
>spreads4 : Symbol(spreads4, Decl(file.tsx, 12, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>p1 : Symbol(p1, Decl(file.tsx, 8, 3))
>x : Symbol(unknown)
>p3 : Symbol(p3, Decl(file.tsx, 8, 11))
>p2 : Symbol(p2, Decl(file.tsx, 8, 7))
>x : Symbol(x, Decl(file.tsx, 12, 27))
>p3 : Symbol(p3, Decl(file.tsx, 8, 21))
>p2 : Symbol(p2, Decl(file.tsx, 8, 12))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
var spreads5 = <div x={p2} {...p1} y={p3}>{p2}</div>;
>spreads5 : Symbol(spreads5, Decl(file.tsx, 13, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
>x : Symbol(unknown)
>p2 : Symbol(p2, Decl(file.tsx, 8, 7))
>x : Symbol(x, Decl(file.tsx, 13, 19))
>p2 : Symbol(p2, Decl(file.tsx, 8, 12))
>p1 : Symbol(p1, Decl(file.tsx, 8, 3))
>y : Symbol(unknown)
>p3 : Symbol(p3, Decl(file.tsx, 8, 11))
>p2 : Symbol(p2, Decl(file.tsx, 8, 7))
>y : Symbol(y, Decl(file.tsx, 13, 34))
>p3 : Symbol(p3, Decl(file.tsx, 8, 21))
>p2 : Symbol(p2, Decl(file.tsx, 8, 12))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
@@ -15,7 +15,7 @@ declare module JSX {
declare var React: any;
>React : any
var p1, p2, p3;
var p1: any, p2: any, p3: any;
>p1 : any
>p2 : any
>p3 : any
@@ -10,7 +10,7 @@ tests/cases/conformance/jsx/file.tsx(12,5): error TS2304: Cannot find name 'blah
}
declare var React: any;
var p;
var p: any;
var openClosed1 = <div>
{blah}
+1 -1
View File
@@ -7,7 +7,7 @@ declare module JSX {
}
declare var React: any;
var p;
var p: any;
var openClosed1 = <div>
{blah}
+1 -1
View File
@@ -16,7 +16,7 @@ export var React;
import {React} from "./test";
// Should emit test_1.React.createElement
// and React.__spread
var foo;
var foo: any;
var spread1 = <div x='' {...foo} y='' />;
@@ -24,13 +24,13 @@ import {React} from "./test";
// Should emit test_1.React.createElement
// and React.__spread
var foo;
var foo: any;
>foo : Symbol(foo, Decl(react-consumer.tsx, 3, 3))
var spread1 = <div x='' {...foo} y='' />;
>spread1 : Symbol(spread1, Decl(react-consumer.tsx, 4, 3))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 2, 22))
>x : Symbol(unknown)
>x : Symbol(x, Decl(react-consumer.tsx, 4, 18))
>foo : Symbol(foo, Decl(react-consumer.tsx, 3, 3))
>y : Symbol(unknown)
>y : Symbol(y, Decl(react-consumer.tsx, 4, 32))
@@ -24,14 +24,14 @@ import {React} from "./test";
// Should emit test_1.React.createElement
// and React.__spread
var foo;
var foo: any;
>foo : any
var spread1 = <div x='' {...foo} y='' />;
>spread1 : JSX.Element
><div x='' {...foo} y='' /> : JSX.Element
>div : any
>x : any
>x : string
>foo : any
>y : any
>y : string
+1 -1
View File
@@ -17,7 +17,7 @@ namespace M {
namespace M {
// Should emit M.React.createElement
// and M.React.__spread
var foo;
var foo: any;
var spread1 = <div x='' {...foo} y='' />;
// Quotes
@@ -27,15 +27,15 @@ namespace M {
// Should emit M.React.createElement
// and M.React.__spread
var foo;
var foo: any;
>foo : Symbol(foo, Decl(react-consumer.tsx, 7, 4))
var spread1 = <div x='' {...foo} y='' />;
>spread1 : Symbol(spread1, Decl(react-consumer.tsx, 8, 4))
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 2, 22))
>x : Symbol(unknown)
>x : Symbol(x, Decl(react-consumer.tsx, 8, 19))
>foo : Symbol(foo, Decl(react-consumer.tsx, 7, 4))
>y : Symbol(unknown)
>y : Symbol(y, Decl(react-consumer.tsx, 8, 33))
// Quotes
var x = <div>This "quote" thing</div>;
@@ -27,16 +27,16 @@ namespace M {
// Should emit M.React.createElement
// and M.React.__spread
var foo;
var foo: any;
>foo : any
var spread1 = <div x='' {...foo} y='' />;
>spread1 : JSX.Element
><div x='' {...foo} y='' /> : JSX.Element
>div : any
>x : any
>x : string
>foo : any
>y : any
>y : string
// Quotes
var x = <div>This "quote" thing</div>;

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