mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Fixed an issue with JSX children expression not being contextually discriminated (#53502)
This commit is contained in:
@@ -29236,7 +29236,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function getContextualTypeForChildJsxExpression(node: JsxElement, child: JsxChild, contextFlags: ContextFlags | undefined) {
|
||||
const attributesType = getApparentTypeOfContextualType(node.openingElement.tagName, contextFlags);
|
||||
const attributesType = getApparentTypeOfContextualType(node.openingElement.attributes, contextFlags);
|
||||
// JSX expression is in children of JSX Element, we will look for an "children" attribute (we get the name from JSX.ElementAttributesProperty)
|
||||
const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(node));
|
||||
if (!(attributesType && !isTypeAny(attributesType) && jsxChildrenPropertyName && jsxChildrenPropertyName !== "")) {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
=== tests/cases/conformance/jsx/checkJsxChildrenProperty16.tsx ===
|
||||
/// <reference path="react16.d.ts" />
|
||||
|
||||
// repro from #53493
|
||||
|
||||
import React = require('react');
|
||||
>React : Symbol(React, Decl(checkJsxChildrenProperty16.tsx, 0, 0))
|
||||
|
||||
export type Props =
|
||||
>Props : Symbol(Props, Decl(checkJsxChildrenProperty16.tsx, 4, 32))
|
||||
|
||||
| { renderNumber?: false; children: (arg: string) => void }
|
||||
>renderNumber : Symbol(renderNumber, Decl(checkJsxChildrenProperty16.tsx, 7, 5))
|
||||
>children : Symbol(children, Decl(checkJsxChildrenProperty16.tsx, 7, 27))
|
||||
>arg : Symbol(arg, Decl(checkJsxChildrenProperty16.tsx, 7, 39))
|
||||
|
||||
| {
|
||||
renderNumber: true;
|
||||
>renderNumber : Symbol(renderNumber, Decl(checkJsxChildrenProperty16.tsx, 8, 5))
|
||||
|
||||
children: (arg: number) => void;
|
||||
>children : Symbol(children, Decl(checkJsxChildrenProperty16.tsx, 9, 25))
|
||||
>arg : Symbol(arg, Decl(checkJsxChildrenProperty16.tsx, 10, 17))
|
||||
|
||||
};
|
||||
|
||||
export declare function Foo(props: Props): JSX.Element;
|
||||
>Foo : Symbol(Foo, Decl(checkJsxChildrenProperty16.tsx, 11, 6))
|
||||
>props : Symbol(props, Decl(checkJsxChildrenProperty16.tsx, 13, 28))
|
||||
>Props : Symbol(Props, Decl(checkJsxChildrenProperty16.tsx, 4, 32))
|
||||
>JSX : Symbol(JSX, Decl(react16.d.ts, 2493, 12))
|
||||
>Element : Symbol(JSX.Element, Decl(react16.d.ts, 2494, 23))
|
||||
|
||||
export const Test = () => {
|
||||
>Test : Symbol(Test, Decl(checkJsxChildrenProperty16.tsx, 15, 12))
|
||||
|
||||
return (
|
||||
<>
|
||||
<Foo>{(value) => {}}</Foo>
|
||||
>Foo : Symbol(Foo, Decl(checkJsxChildrenProperty16.tsx, 11, 6))
|
||||
>value : Symbol(value, Decl(checkJsxChildrenProperty16.tsx, 18, 13))
|
||||
>Foo : Symbol(Foo, Decl(checkJsxChildrenProperty16.tsx, 11, 6))
|
||||
|
||||
<Foo renderNumber>{(value) => {}}</Foo>
|
||||
>Foo : Symbol(Foo, Decl(checkJsxChildrenProperty16.tsx, 11, 6))
|
||||
>renderNumber : Symbol(renderNumber, Decl(checkJsxChildrenProperty16.tsx, 19, 10))
|
||||
>value : Symbol(value, Decl(checkJsxChildrenProperty16.tsx, 19, 26))
|
||||
>Foo : Symbol(Foo, Decl(checkJsxChildrenProperty16.tsx, 11, 6))
|
||||
|
||||
<Foo children={(value) => {}} />
|
||||
>Foo : Symbol(Foo, Decl(checkJsxChildrenProperty16.tsx, 11, 6))
|
||||
>children : Symbol(children, Decl(checkJsxChildrenProperty16.tsx, 21, 10))
|
||||
>value : Symbol(value, Decl(checkJsxChildrenProperty16.tsx, 21, 22))
|
||||
|
||||
<Foo renderNumber children={(value) => {}} />
|
||||
>Foo : Symbol(Foo, Decl(checkJsxChildrenProperty16.tsx, 11, 6))
|
||||
>renderNumber : Symbol(renderNumber, Decl(checkJsxChildrenProperty16.tsx, 22, 10))
|
||||
>children : Symbol(children, Decl(checkJsxChildrenProperty16.tsx, 22, 23))
|
||||
>value : Symbol(value, Decl(checkJsxChildrenProperty16.tsx, 22, 35))
|
||||
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
=== tests/cases/conformance/jsx/checkJsxChildrenProperty16.tsx ===
|
||||
/// <reference path="react16.d.ts" />
|
||||
|
||||
// repro from #53493
|
||||
|
||||
import React = require('react');
|
||||
>React : typeof React
|
||||
|
||||
export type Props =
|
||||
>Props : { renderNumber?: false | undefined; children: (arg: string) => void; } | { renderNumber: true; children: (arg: number) => void; }
|
||||
|
||||
| { renderNumber?: false; children: (arg: string) => void }
|
||||
>renderNumber : false | undefined
|
||||
>false : false
|
||||
>children : (arg: string) => void
|
||||
>arg : string
|
||||
|
||||
| {
|
||||
renderNumber: true;
|
||||
>renderNumber : true
|
||||
>true : true
|
||||
|
||||
children: (arg: number) => void;
|
||||
>children : (arg: number) => void
|
||||
>arg : number
|
||||
|
||||
};
|
||||
|
||||
export declare function Foo(props: Props): JSX.Element;
|
||||
>Foo : (props: Props) => JSX.Element
|
||||
>props : Props
|
||||
>JSX : any
|
||||
|
||||
export const Test = () => {
|
||||
>Test : () => JSX.Element
|
||||
>() => { return ( <> <Foo>{(value) => {}}</Foo> <Foo renderNumber>{(value) => {}}</Foo> <Foo children={(value) => {}} /> <Foo renderNumber children={(value) => {}} /> </> );} : () => JSX.Element
|
||||
|
||||
return (
|
||||
>( <> <Foo>{(value) => {}}</Foo> <Foo renderNumber>{(value) => {}}</Foo> <Foo children={(value) => {}} /> <Foo renderNumber children={(value) => {}} /> </> ) : JSX.Element
|
||||
|
||||
<>
|
||||
><> <Foo>{(value) => {}}</Foo> <Foo renderNumber>{(value) => {}}</Foo> <Foo children={(value) => {}} /> <Foo renderNumber children={(value) => {}} /> </> : JSX.Element
|
||||
|
||||
<Foo>{(value) => {}}</Foo>
|
||||
><Foo>{(value) => {}}</Foo> : JSX.Element
|
||||
>Foo : (props: Props) => JSX.Element
|
||||
>(value) => {} : (value: string) => void
|
||||
>value : string
|
||||
>Foo : (props: Props) => JSX.Element
|
||||
|
||||
<Foo renderNumber>{(value) => {}}</Foo>
|
||||
><Foo renderNumber>{(value) => {}}</Foo> : JSX.Element
|
||||
>Foo : (props: Props) => JSX.Element
|
||||
>renderNumber : true
|
||||
>(value) => {} : (value: number) => void
|
||||
>value : number
|
||||
>Foo : (props: Props) => JSX.Element
|
||||
|
||||
<Foo children={(value) => {}} />
|
||||
><Foo children={(value) => {}} /> : JSX.Element
|
||||
>Foo : (props: Props) => JSX.Element
|
||||
>children : (value: string) => void
|
||||
>(value) => {} : (value: string) => void
|
||||
>value : string
|
||||
|
||||
<Foo renderNumber children={(value) => {}} />
|
||||
><Foo renderNumber children={(value) => {}} /> : JSX.Element
|
||||
>Foo : (props: Props) => JSX.Element
|
||||
>renderNumber : true
|
||||
>children : (value: number) => void
|
||||
>(value) => {} : (value: number) => void
|
||||
>value : number
|
||||
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
// @strict: true
|
||||
// @noEmit: true
|
||||
// @jsx: preserve
|
||||
|
||||
/// <reference path="/.lib/react16.d.ts" />
|
||||
|
||||
// repro from #53493
|
||||
|
||||
import React = require('react');
|
||||
|
||||
export type Props =
|
||||
| { renderNumber?: false; children: (arg: string) => void }
|
||||
| {
|
||||
renderNumber: true;
|
||||
children: (arg: number) => void;
|
||||
};
|
||||
|
||||
export declare function Foo(props: Props): JSX.Element;
|
||||
|
||||
export const Test = () => {
|
||||
return (
|
||||
<>
|
||||
<Foo>{(value) => {}}</Foo>
|
||||
<Foo renderNumber>{(value) => {}}</Foo>
|
||||
|
||||
<Foo children={(value) => {}} />
|
||||
<Foo renderNumber children={(value) => {}} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user