mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #13640 from Microsoft/wip-master-statelessOverload
Using overload to figure out function signature for SFC
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace ts {
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.CatchClause:
|
||||
case SyntaxKind.JsxAttribute:
|
||||
return SemanticMeaning.Value;
|
||||
|
||||
case SyntaxKind.TypeParameter:
|
||||
|
||||
+12
-4
@@ -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
|
||||
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -7,7 +7,7 @@ declare module JSX {
|
||||
}
|
||||
declare var React: any;
|
||||
|
||||
var p;
|
||||
var p: any;
|
||||
var openClosed1 = <div>
|
||||
|
||||
{blah}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user