mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Use inference for filling JSX attributes in getJsxElementInstanceType (#20973)
* Add simple type inference for JSX elements * Small cleanups from PR feedback
This commit is contained in:
+36
-19
@@ -15043,7 +15043,7 @@ namespace ts {
|
||||
* element is not a class element, or the class element type cannot be determined, returns 'undefined'.
|
||||
* For example, in the element <MyClass>, the element instance type is `MyClass` (not `typeof MyClass`).
|
||||
*/
|
||||
function getJsxElementInstanceType(node: JsxOpeningLikeElement, valueType: Type) {
|
||||
function getJsxElementInstanceType(node: JsxOpeningLikeElement, valueType: Type, sourceAttributesType: Type) {
|
||||
Debug.assert(!(valueType.flags & TypeFlags.Union));
|
||||
if (isTypeAny(valueType)) {
|
||||
// Short-circuit if the class tag is using an element type 'any'
|
||||
@@ -15066,7 +15066,8 @@ namespace ts {
|
||||
for (const signature of signatures) {
|
||||
if (signature.typeParameters) {
|
||||
const isJavascript = isInJavaScriptFile(node);
|
||||
const typeArguments = fillMissingTypeArguments(/*typeArguments*/ undefined, signature.typeParameters, /*minTypeArgumentCount*/ 0, isJavascript);
|
||||
const inferenceContext = createInferenceContext(signature, /*flags*/ isJavascript ? InferenceFlags.AnyDefault : 0);
|
||||
const typeArguments = inferJsxTypeArguments(signature, sourceAttributesType, inferenceContext);
|
||||
instantiatedSignatures.push(getSignatureInstantiation(signature, typeArguments, isJavascript));
|
||||
}
|
||||
else {
|
||||
@@ -15251,6 +15252,7 @@ namespace ts {
|
||||
*
|
||||
* @param openingLikeElement a non-intrinsic JSXOPeningLikeElement
|
||||
* @param shouldIncludeAllStatelessAttributesType a boolean indicating whether to include all attributes types from all stateless function signature
|
||||
* @param sourceAttributesType Is the attributes type the user passed, and is used to create inferences in the target type if present
|
||||
* @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
|
||||
@@ -15259,13 +15261,14 @@ namespace ts {
|
||||
*/
|
||||
function resolveCustomJsxElementAttributesType(openingLikeElement: JsxOpeningLikeElement,
|
||||
shouldIncludeAllStatelessAttributesType: boolean,
|
||||
elementType: Type = checkExpression(openingLikeElement.tagName),
|
||||
sourceAttributesType: Type | undefined,
|
||||
elementType: Type,
|
||||
elementClassType?: Type): Type {
|
||||
|
||||
if (elementType.flags & TypeFlags.Union) {
|
||||
const types = (elementType as UnionType).types;
|
||||
return getUnionType(types.map(type => {
|
||||
return resolveCustomJsxElementAttributesType(openingLikeElement, shouldIncludeAllStatelessAttributesType, type, elementClassType);
|
||||
return resolveCustomJsxElementAttributesType(openingLikeElement, shouldIncludeAllStatelessAttributesType, sourceAttributesType, type, elementClassType);
|
||||
}), UnionReduction.Subtype);
|
||||
}
|
||||
|
||||
@@ -15296,7 +15299,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Get the element instance type (the result of newing or invoking this tag)
|
||||
const elemInstanceType = getJsxElementInstanceType(openingLikeElement, elementType);
|
||||
const elemInstanceType = getJsxElementInstanceType(openingLikeElement, elementType, sourceAttributesType || emptyObjectType);
|
||||
|
||||
// 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.
|
||||
@@ -15309,7 +15312,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Issue an error if this return type isn't assignable to JSX.ElementClass
|
||||
if (elementClassType) {
|
||||
if (elementClassType && sourceAttributesType) {
|
||||
checkTypeRelatedTo(elemInstanceType, elementClassType, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
|
||||
}
|
||||
|
||||
@@ -15392,14 +15395,20 @@ namespace ts {
|
||||
* @param node a custom JSX opening-like element
|
||||
* @param shouldIncludeAllStatelessAttributesType a boolean value used by language service to get all possible attributes type from an overload stateless function component
|
||||
*/
|
||||
function getCustomJsxElementAttributesType(node: JsxOpeningLikeElement, shouldIncludeAllStatelessAttributesType: boolean): Type {
|
||||
const links = getNodeLinks(node);
|
||||
const linkLocation = shouldIncludeAllStatelessAttributesType ? "resolvedJsxElementAllAttributesType" : "resolvedJsxElementAttributesType";
|
||||
if (!links[linkLocation]) {
|
||||
const elemClassType = getJsxGlobalElementClassType();
|
||||
return links[linkLocation] = resolveCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType, /*elementType*/ undefined, elemClassType);
|
||||
function getCustomJsxElementAttributesType(node: JsxOpeningLikeElement, sourceAttributesType: Type, shouldIncludeAllStatelessAttributesType: boolean): Type {
|
||||
if (!sourceAttributesType) {
|
||||
// This ensures we cache non-inference uses of this calculation (ie, contextual types or services)
|
||||
const links = getNodeLinks(node);
|
||||
const linkLocation = shouldIncludeAllStatelessAttributesType ? "resolvedJsxElementAllAttributesType" : "resolvedJsxElementAttributesType";
|
||||
if (!links[linkLocation]) {
|
||||
const elemClassType = getJsxGlobalElementClassType();
|
||||
return links[linkLocation] = resolveCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType, sourceAttributesType, checkExpression(node.tagName), elemClassType);
|
||||
}
|
||||
return links[linkLocation];
|
||||
}
|
||||
else {
|
||||
return resolveCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType, sourceAttributesType, checkExpression(node.tagName), getJsxGlobalElementClassType());
|
||||
}
|
||||
return links[linkLocation];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -15414,7 +15423,7 @@ namespace ts {
|
||||
else {
|
||||
// Because in language service, the given JSX opening-like element may be incomplete and therefore,
|
||||
// we can't resolve to exact signature if the element is a stateless function component so the best thing to do is return all attributes type from all overloads.
|
||||
return getCustomJsxElementAttributesType(node, /*shouldIncludeAllStatelessAttributesType*/ true);
|
||||
return getCustomJsxElementAttributesType(node, /*sourceAttributesType*/ undefined, /*shouldIncludeAllStatelessAttributesType*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15428,7 +15437,7 @@ namespace ts {
|
||||
return getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node);
|
||||
}
|
||||
else {
|
||||
return getCustomJsxElementAttributesType(node, /*shouldIncludeAllStatelessAttributesType*/ false);
|
||||
return getCustomJsxElementAttributesType(node, /*sourceAttributesType*/ undefined, /*shouldIncludeAllStatelessAttributesType*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15567,16 +15576,17 @@ namespace ts {
|
||||
// 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, checkMode);
|
||||
|
||||
// targetAttributesType is a type of an attributes from resolving tagName of an opening-like JSX element.
|
||||
const targetAttributesType = isJsxIntrinsicIdentifier(openingLikeElement.tagName) ?
|
||||
getIntrinsicAttributesTypeFromJsxOpeningLikeElement(openingLikeElement) :
|
||||
getCustomJsxElementAttributesType(openingLikeElement, sourceAttributesType, /*shouldIncludeAllStatelessAttributesType*/ false);
|
||||
|
||||
// If the targetAttributesType is an emptyObjectType, indicating that there is no property named 'props' on this instance type.
|
||||
// but there exists a sourceAttributesType, we need to explicitly give an error as normal assignability check allow excess properties and will pass.
|
||||
if (targetAttributesType === emptyObjectType && (isTypeAny(sourceAttributesType) || (<ResolvedType>sourceAttributesType).properties.length > 0)) {
|
||||
@@ -16434,6 +16444,13 @@ namespace ts {
|
||||
return getSignatureInstantiation(signature, getInferredTypes(context), isInJavaScriptFile(contextualSignature.declaration));
|
||||
}
|
||||
|
||||
function inferJsxTypeArguments(signature: Signature, sourceAttributesType: Type, context: InferenceContext): Type[] {
|
||||
const paramType = getTypeAtPosition(signature, 0);
|
||||
inferTypes(context.inferences, sourceAttributesType, paramType);
|
||||
|
||||
return getInferredTypes(context);
|
||||
}
|
||||
|
||||
function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray<Expression>, excludeArgument: boolean[], context: InferenceContext): Type[] {
|
||||
// Clear out all the inference results from the last time inferTypeArguments was called on this context
|
||||
for (const inference of context.inferences) {
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
tests/cases/conformance/jsx/file.tsx(11,36): error TS2339: Property 'x' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<B1<{}>> & { children?: ReactNode; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
|
||||
import React = require('react');
|
||||
|
||||
class B1<T extends { x: string }> extends React.Component<T, {}> {
|
||||
render() {
|
||||
return <div>hi</div>;
|
||||
}
|
||||
}
|
||||
class B<U> extends React.Component<U, {}> {
|
||||
render() {
|
||||
// Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object
|
||||
return <B1 {...this.props} x="hi" />;
|
||||
~~~~~~
|
||||
!!! error TS2339: Property 'x' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<B1<{}>> & { children?: ReactNode; }'.
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ class B1<T extends { x: string }> extends React.Component<T, {}> {
|
||||
}
|
||||
class B<U> extends React.Component<U, {}> {
|
||||
render() {
|
||||
// Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object
|
||||
return <B1 {...this.props} x="hi" />;
|
||||
}
|
||||
}
|
||||
@@ -43,7 +42,6 @@ var B = /** @class */ (function (_super) {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
B.prototype.render = function () {
|
||||
// Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object
|
||||
return <B1 {...this.props} x="hi"/>;
|
||||
};
|
||||
return B;
|
||||
|
||||
@@ -30,12 +30,11 @@ class B<U> extends React.Component<U, {}> {
|
||||
render() {
|
||||
>render : Symbol(B.render, Decl(file.tsx, 7, 43))
|
||||
|
||||
// Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object
|
||||
return <B1 {...this.props} x="hi" />;
|
||||
>B1 : Symbol(B1, Decl(file.tsx, 0, 32))
|
||||
>this.props : Symbol(React.Component.props, Decl(react.d.ts, 167, 37))
|
||||
>this : Symbol(B, Decl(file.tsx, 6, 1))
|
||||
>props : Symbol(React.Component.props, Decl(react.d.ts, 167, 37))
|
||||
>x : Symbol(x, Decl(file.tsx, 10, 34))
|
||||
>x : Symbol(x, Decl(file.tsx, 9, 34))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ class B<U> extends React.Component<U, {}> {
|
||||
render() {
|
||||
>render : () => JSX.Element
|
||||
|
||||
// Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object
|
||||
return <B1 {...this.props} x="hi" />;
|
||||
><B1 {...this.props} x="hi" /> : JSX.Element
|
||||
>B1 : typeof B1
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
tests/cases/conformance/jsx/file.tsx(12,36): error TS2339: Property 'x' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<B1<{}>> & { children?: ReactNode; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
|
||||
import React = require('react');
|
||||
|
||||
class B1<T extends { x: string }> extends React.Component<T, {}> {
|
||||
render() {
|
||||
return <div>hi</div>;
|
||||
}
|
||||
}
|
||||
class B<U> extends React.Component<U, {}> {
|
||||
props: U;
|
||||
render() {
|
||||
// Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object
|
||||
return <B1 {...this.props} x="hi" />;
|
||||
~~~~~~
|
||||
!!! error TS2339: Property 'x' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<B1<{}>> & { children?: ReactNode; }'.
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ class B1<T extends { x: string }> extends React.Component<T, {}> {
|
||||
class B<U> extends React.Component<U, {}> {
|
||||
props: U;
|
||||
render() {
|
||||
// Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object
|
||||
return <B1 {...this.props} x="hi" />;
|
||||
}
|
||||
}
|
||||
@@ -44,7 +43,6 @@ var B = /** @class */ (function (_super) {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
B.prototype.render = function () {
|
||||
// Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object
|
||||
return <B1 {...this.props} x="hi"/>;
|
||||
};
|
||||
return B;
|
||||
|
||||
@@ -34,12 +34,11 @@ class B<U> extends React.Component<U, {}> {
|
||||
render() {
|
||||
>render : Symbol(B.render, Decl(file.tsx, 8, 13))
|
||||
|
||||
// Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object
|
||||
return <B1 {...this.props} x="hi" />;
|
||||
>B1 : Symbol(B1, Decl(file.tsx, 0, 32))
|
||||
>this.props : Symbol(B.props, Decl(file.tsx, 7, 43))
|
||||
>this : Symbol(B, Decl(file.tsx, 6, 1))
|
||||
>props : Symbol(B.props, Decl(file.tsx, 7, 43))
|
||||
>x : Symbol(x, Decl(file.tsx, 11, 34))
|
||||
>x : Symbol(x, Decl(file.tsx, 10, 34))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ class B<U> extends React.Component<U, {}> {
|
||||
render() {
|
||||
>render : () => JSX.Element
|
||||
|
||||
// Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object
|
||||
return <B1 {...this.props} x="hi" />;
|
||||
><B1 {...this.props} x="hi" /> : JSX.Element
|
||||
>B1 : typeof B1
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
tests/cases/conformance/jsx/file.tsx(13,9): error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<Prop>> & Prop & { children?: ReactNode; }'.
|
||||
Type '{}' is not assignable to type 'Prop'.
|
||||
Property 'a' is missing in type '{}'.
|
||||
tests/cases/conformance/jsx/file.tsx(14,18): error TS2322: Type '{ a: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<Prop>> & Prop & { children?: ReactNode; }'.
|
||||
Type '{ a: string; }' is not assignable to type 'Prop'.
|
||||
Property 'b' is missing in type '{ a: string; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/file.tsx (2 errors) ====
|
||||
import React = require('react');
|
||||
|
||||
interface Prop {
|
||||
a: number,
|
||||
b: string
|
||||
}
|
||||
|
||||
declare class MyComp<P = Prop> extends React.Component<P, {}> {
|
||||
internalProp: P;
|
||||
}
|
||||
|
||||
// Error
|
||||
let x = <MyComp />
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<Prop>> & Prop & { children?: ReactNode; }'.
|
||||
!!! error TS2322: Type '{}' is not assignable to type 'Prop'.
|
||||
!!! error TS2322: Property 'a' is missing in type '{}'.
|
||||
let x1 = <MyComp a="hi"/>
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '{ a: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<Prop>> & Prop & { children?: ReactNode; }'.
|
||||
!!! error TS2322: Type '{ a: string; }' is not assignable to type 'Prop'.
|
||||
!!! error TS2322: Property 'b' is missing in type '{ a: string; }'.
|
||||
@@ -10,7 +10,6 @@ declare class MyComp<P = Prop> extends React.Component<P, {}> {
|
||||
internalProp: P;
|
||||
}
|
||||
|
||||
// Error
|
||||
let x = <MyComp />
|
||||
let x1 = <MyComp a="hi"/>
|
||||
|
||||
@@ -18,6 +17,5 @@ let x1 = <MyComp a="hi"/>
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var React = require("react");
|
||||
// Error
|
||||
var x = <MyComp />;
|
||||
var x1 = <MyComp a="hi"/>;
|
||||
|
||||
@@ -26,13 +26,12 @@ declare class MyComp<P = Prop> extends React.Component<P, {}> {
|
||||
>P : Symbol(P, Decl(file.tsx, 7, 21))
|
||||
}
|
||||
|
||||
// Error
|
||||
let x = <MyComp />
|
||||
>x : Symbol(x, Decl(file.tsx, 12, 3))
|
||||
>x : Symbol(x, Decl(file.tsx, 11, 3))
|
||||
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
|
||||
|
||||
let x1 = <MyComp a="hi"/>
|
||||
>x1 : Symbol(x1, Decl(file.tsx, 13, 3))
|
||||
>x1 : Symbol(x1, Decl(file.tsx, 12, 3))
|
||||
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
|
||||
>a : Symbol(a, Decl(file.tsx, 13, 16))
|
||||
>a : Symbol(a, Decl(file.tsx, 12, 16))
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ declare class MyComp<P = Prop> extends React.Component<P, {}> {
|
||||
>P : P
|
||||
}
|
||||
|
||||
// Error
|
||||
let x = <MyComp />
|
||||
>x : JSX.Element
|
||||
><MyComp /> : JSX.Element
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
tests/cases/conformance/jsx/file.tsx(16,17): error TS2559: Type '{ a: number; b: string; }' has no properties in common with type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<{}>> & { children?: ReactNode; }'.
|
||||
tests/cases/conformance/jsx/file.tsx(17,18): error TS2559: Type '{ a: string; }' has no properties in common with type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<{}>> & { children?: ReactNode; }'.
|
||||
tests/cases/conformance/jsx/file.tsx(13,10): error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<Prop>> & Prop & { children?: ReactNode; }'.
|
||||
Type '{}' is not assignable to type 'Prop'.
|
||||
Property 'a' is missing in type '{}'.
|
||||
tests/cases/conformance/jsx/file.tsx(19,18): error TS2322: Type '{ a: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<Prop>> & Prop & { children?: ReactNode; }'.
|
||||
Type '{ a: string; }' is not assignable to type 'Prop'.
|
||||
Property 'b' is missing in type '{ a: string; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/file.tsx (2 errors) ====
|
||||
@@ -14,13 +18,19 @@ tests/cases/conformance/jsx/file.tsx(17,18): error TS2559: Type '{ a: string; }'
|
||||
internalProp: P;
|
||||
}
|
||||
|
||||
// OK: we fille in missing type argument with empty object
|
||||
// Error
|
||||
let x1 = <MyComp />
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<Prop>> & Prop & { children?: ReactNode; }'.
|
||||
!!! error TS2322: Type '{}' is not assignable to type 'Prop'.
|
||||
!!! error TS2322: Property 'a' is missing in type '{}'.
|
||||
|
||||
// OK
|
||||
let x = <MyComp a={10} b="hi" />
|
||||
|
||||
// Error
|
||||
let x = <MyComp a={10} b="hi" />
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2559: Type '{ a: number; b: string; }' has no properties in common with type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<{}>> & { children?: ReactNode; }'.
|
||||
let x2 = <MyComp a="hi"/>
|
||||
~~~~~~
|
||||
!!! error TS2559: Type '{ a: string; }' has no properties in common with type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<{}>> & { children?: ReactNode; }'.
|
||||
!!! error TS2322: Type '{ a: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<Prop>> & Prop & { children?: ReactNode; }'.
|
||||
!!! error TS2322: Type '{ a: string; }' is not assignable to type 'Prop'.
|
||||
!!! error TS2322: Property 'b' is missing in type '{ a: string; }'.
|
||||
@@ -10,19 +10,22 @@ declare class MyComp<P extends Prop> extends React.Component<P, {}> {
|
||||
internalProp: P;
|
||||
}
|
||||
|
||||
// OK: we fille in missing type argument with empty object
|
||||
// Error
|
||||
let x1 = <MyComp />
|
||||
|
||||
// Error
|
||||
// OK
|
||||
let x = <MyComp a={10} b="hi" />
|
||||
|
||||
// Error
|
||||
let x2 = <MyComp a="hi"/>
|
||||
|
||||
//// [file.jsx]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var React = require("react");
|
||||
// OK: we fille in missing type argument with empty object
|
||||
var x1 = <MyComp />;
|
||||
// Error
|
||||
var x1 = <MyComp />;
|
||||
// OK
|
||||
var x = <MyComp a={10} b="hi"/>;
|
||||
// Error
|
||||
var x2 = <MyComp a="hi"/>;
|
||||
|
||||
@@ -26,20 +26,21 @@ declare class MyComp<P extends Prop> extends React.Component<P, {}> {
|
||||
>P : Symbol(P, Decl(file.tsx, 7, 21))
|
||||
}
|
||||
|
||||
// OK: we fille in missing type argument with empty object
|
||||
// Error
|
||||
let x1 = <MyComp />
|
||||
>x1 : Symbol(x1, Decl(file.tsx, 12, 3))
|
||||
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
|
||||
|
||||
// Error
|
||||
// OK
|
||||
let x = <MyComp a={10} b="hi" />
|
||||
>x : Symbol(x, Decl(file.tsx, 15, 3))
|
||||
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
|
||||
>a : Symbol(a, Decl(file.tsx, 15, 15))
|
||||
>b : Symbol(b, Decl(file.tsx, 15, 22))
|
||||
|
||||
// Error
|
||||
let x2 = <MyComp a="hi"/>
|
||||
>x2 : Symbol(x2, Decl(file.tsx, 16, 3))
|
||||
>x2 : Symbol(x2, Decl(file.tsx, 18, 3))
|
||||
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
|
||||
>a : Symbol(a, Decl(file.tsx, 16, 16))
|
||||
>a : Symbol(a, Decl(file.tsx, 18, 16))
|
||||
|
||||
|
||||
@@ -26,13 +26,13 @@ declare class MyComp<P extends Prop> extends React.Component<P, {}> {
|
||||
>P : P
|
||||
}
|
||||
|
||||
// OK: we fille in missing type argument with empty object
|
||||
// Error
|
||||
let x1 = <MyComp />
|
||||
>x1 : JSX.Element
|
||||
><MyComp /> : JSX.Element
|
||||
>MyComp : typeof MyComp
|
||||
|
||||
// Error
|
||||
// OK
|
||||
let x = <MyComp a={10} b="hi" />
|
||||
>x : JSX.Element
|
||||
><MyComp a={10} b="hi" /> : JSX.Element
|
||||
@@ -41,6 +41,7 @@ let x = <MyComp a={10} b="hi" />
|
||||
>10 : 10
|
||||
>b : string
|
||||
|
||||
// Error
|
||||
let x2 = <MyComp a="hi"/>
|
||||
>x2 : JSX.Element
|
||||
><MyComp a="hi"/> : JSX.Element
|
||||
|
||||
@@ -13,7 +13,6 @@ class B1<T extends { x: string }> extends React.Component<T, {}> {
|
||||
}
|
||||
class B<U> extends React.Component<U, {}> {
|
||||
render() {
|
||||
// Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object
|
||||
return <B1 {...this.props} x="hi" />;
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@ class B1<T extends { x: string }> extends React.Component<T, {}> {
|
||||
class B<U> extends React.Component<U, {}> {
|
||||
props: U;
|
||||
render() {
|
||||
// Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object
|
||||
return <B1 {...this.props} x="hi" />;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,5 @@ declare class MyComp<P = Prop> extends React.Component<P, {}> {
|
||||
internalProp: P;
|
||||
}
|
||||
|
||||
// Error
|
||||
let x = <MyComp />
|
||||
let x1 = <MyComp a="hi"/>
|
||||
@@ -15,9 +15,11 @@ declare class MyComp<P extends Prop> extends React.Component<P, {}> {
|
||||
internalProp: P;
|
||||
}
|
||||
|
||||
// OK: we fille in missing type argument with empty object
|
||||
// Error
|
||||
let x1 = <MyComp />
|
||||
|
||||
// Error
|
||||
// OK
|
||||
let x = <MyComp a={10} b="hi" />
|
||||
|
||||
// Error
|
||||
let x2 = <MyComp a="hi"/>
|
||||
Reference in New Issue
Block a user