Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions internal/checker/jsx.go
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme
childrenPropSymbol.ValueDeclaration.AsPropertySignatureDeclaration().Symbol = childrenPropSymbol
childPropMap := make(ast.SymbolTable)
childPropMap[jsxChildrenPropertyName] = childrenPropSymbol
spread = c.getSpreadType(spread, c.newAnonymousType(attributesSymbol, childPropMap, nil, nil, nil), attributesSymbol, objectFlags, false /*readonly*/)
spread = c.getSpreadType(spread, c.newAnonymousType(attributesSymbol, childPropMap, nil, nil, nil), attributesSymbol, objectFlags|c.getPropagatingFlagsOfTypes(childTypes, TypeFlagsNone), false /*readonly*/)
}
}
if hasSpreadAnyType {
Expand Down Expand Up @@ -888,8 +888,7 @@ func (c *Checker) checkJsxChildren(node *ast.Node, checkMode CheckMode) []*Type
// empty jsx expressions don't *really* count as present children
continue
} else {
t := c.checkExpressionForMutableLocation(child, checkMode)
childTypes = append(childTypes, core.IfElse(t != c.anyFunctionType, t, c.emptyJsxObjectType))
childTypes = append(childTypes, c.checkExpressionForMutableLocation(child, checkMode))
}
}
return childTypes
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
//// [tests/cases/compiler/contextuallyTypedJsxChildren2.tsx] ////

=== contextuallyTypedJsxChildren2.tsx ===
/// <reference path="react16.d.ts" />

// https://github.com/microsoft/typescript-go/issues/2802

import * as React from 'react';
>React : Symbol(React, Decl(contextuallyTypedJsxChildren2.tsx, 4, 6))

declare const TestComponentWithChildren: <T, TParam>(props: {
>TestComponentWithChildren : Symbol(TestComponentWithChildren, Decl(contextuallyTypedJsxChildren2.tsx, 6, 13))
>T : Symbol(T, Decl(contextuallyTypedJsxChildren2.tsx, 6, 42))
>TParam : Symbol(TParam, Decl(contextuallyTypedJsxChildren2.tsx, 6, 44))
>props : Symbol(props, Decl(contextuallyTypedJsxChildren2.tsx, 6, 53))

state: T;
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 6, 61))
>T : Symbol(T, Decl(contextuallyTypedJsxChildren2.tsx, 6, 42))

selector?: (state: NoInfer<T>) => TParam;
>selector : Symbol(selector, Decl(contextuallyTypedJsxChildren2.tsx, 7, 11))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 8, 14))
>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(contextuallyTypedJsxChildren2.tsx, 6, 42))
>TParam : Symbol(TParam, Decl(contextuallyTypedJsxChildren2.tsx, 6, 44))

children?: (state: NoInfer<TParam>) => React.ReactElement<any> | null;
>children : Symbol(children, Decl(contextuallyTypedJsxChildren2.tsx, 8, 43))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 9, 14))
>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
>TParam : Symbol(TParam, Decl(contextuallyTypedJsxChildren2.tsx, 6, 44))
>React : Symbol(React, Decl(contextuallyTypedJsxChildren2.tsx, 4, 6))
>ReactElement : Symbol(React.ReactElement, Decl(react16.d.ts, 135, 9))

}) => React.ReactElement<any>;
>React : Symbol(React, Decl(contextuallyTypedJsxChildren2.tsx, 4, 6))
>ReactElement : Symbol(React.ReactElement, Decl(react16.d.ts, 135, 9))

declare const TestComponentWithoutChildren: <T, TParam>(props: {
>TestComponentWithoutChildren : Symbol(TestComponentWithoutChildren, Decl(contextuallyTypedJsxChildren2.tsx, 12, 13))
>T : Symbol(T, Decl(contextuallyTypedJsxChildren2.tsx, 12, 45))
>TParam : Symbol(TParam, Decl(contextuallyTypedJsxChildren2.tsx, 12, 47))
>props : Symbol(props, Decl(contextuallyTypedJsxChildren2.tsx, 12, 56))

state: T;
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 12, 64))
>T : Symbol(T, Decl(contextuallyTypedJsxChildren2.tsx, 12, 45))

selector?: (state: NoInfer<T>) => TParam;
>selector : Symbol(selector, Decl(contextuallyTypedJsxChildren2.tsx, 13, 11))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 14, 14))
>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(contextuallyTypedJsxChildren2.tsx, 12, 45))
>TParam : Symbol(TParam, Decl(contextuallyTypedJsxChildren2.tsx, 12, 47))

notChildren?: (state: NoInfer<TParam>) => React.ReactElement<any> | null;
>notChildren : Symbol(notChildren, Decl(contextuallyTypedJsxChildren2.tsx, 14, 43))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 15, 17))
>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
>TParam : Symbol(TParam, Decl(contextuallyTypedJsxChildren2.tsx, 12, 47))
>React : Symbol(React, Decl(contextuallyTypedJsxChildren2.tsx, 4, 6))
>ReactElement : Symbol(React.ReactElement, Decl(react16.d.ts, 135, 9))

}) => React.ReactElement<any>;
>React : Symbol(React, Decl(contextuallyTypedJsxChildren2.tsx, 4, 6))
>ReactElement : Symbol(React.ReactElement, Decl(react16.d.ts, 135, 9))

const App = () => {
>App : Symbol(App, Decl(contextuallyTypedJsxChildren2.tsx, 18, 5))

return (
<>
<TestComponentWithChildren state={{ foo: 123 }} selector={(state) => state.foo}>
>TestComponentWithChildren : Symbol(TestComponentWithChildren, Decl(contextuallyTypedJsxChildren2.tsx, 6, 13))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 21, 32))
>foo : Symbol(foo, Decl(contextuallyTypedJsxChildren2.tsx, 21, 41))
>selector : Symbol(selector, Decl(contextuallyTypedJsxChildren2.tsx, 21, 53))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 21, 65))
>state.foo : Symbol(foo, Decl(contextuallyTypedJsxChildren2.tsx, 21, 41))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 21, 65))
>foo : Symbol(foo, Decl(contextuallyTypedJsxChildren2.tsx, 21, 41))

{(selected) => <div>{Math.max(selected, 0)}</div>}
>selected : Symbol(selected, Decl(contextuallyTypedJsxChildren2.tsx, 22, 10))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2548, 114))
>Math.max : Symbol(Math.max, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>max : Symbol(Math.max, Decl(lib.es5.d.ts, --, --))
>selected : Symbol(selected, Decl(contextuallyTypedJsxChildren2.tsx, 22, 10))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2548, 114))

</TestComponentWithChildren>
>TestComponentWithChildren : Symbol(TestComponentWithChildren, Decl(contextuallyTypedJsxChildren2.tsx, 6, 13))

<TestComponentWithoutChildren
>TestComponentWithoutChildren : Symbol(TestComponentWithoutChildren, Decl(contextuallyTypedJsxChildren2.tsx, 12, 13))

state={{ foo: 123 }}
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 25, 35))
>foo : Symbol(foo, Decl(contextuallyTypedJsxChildren2.tsx, 26, 16))

selector={(state) => state.foo}
>selector : Symbol(selector, Decl(contextuallyTypedJsxChildren2.tsx, 26, 28))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 27, 19))
>state.foo : Symbol(foo, Decl(contextuallyTypedJsxChildren2.tsx, 26, 16))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 27, 19))
>foo : Symbol(foo, Decl(contextuallyTypedJsxChildren2.tsx, 26, 16))

notChildren={(selected) => <div>{Math.max(selected, 0)}</div>}
>notChildren : Symbol(notChildren, Decl(contextuallyTypedJsxChildren2.tsx, 27, 39))
>selected : Symbol(selected, Decl(contextuallyTypedJsxChildren2.tsx, 28, 22))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2548, 114))
>Math.max : Symbol(Math.max, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>max : Symbol(Math.max, Decl(lib.es5.d.ts, --, --))
>selected : Symbol(selected, Decl(contextuallyTypedJsxChildren2.tsx, 28, 22))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2548, 114))

/>
</>
);
};

// https://github.com/microsoft/typescript-go/issues/2797

interface State {
>State : Symbol(State, Decl(contextuallyTypedJsxChildren2.tsx, 32, 2))

value: boolean
>value : Symbol(State.value, Decl(contextuallyTypedJsxChildren2.tsx, 36, 17))
}

declare const Subscribe: <TSelected = State>(props: {
>Subscribe : Symbol(Subscribe, Decl(contextuallyTypedJsxChildren2.tsx, 40, 13))
>TSelected : Symbol(TSelected, Decl(contextuallyTypedJsxChildren2.tsx, 40, 26))
>State : Symbol(State, Decl(contextuallyTypedJsxChildren2.tsx, 32, 2))
>props : Symbol(props, Decl(contextuallyTypedJsxChildren2.tsx, 40, 45))

selector?: (state: State) => TSelected
>selector : Symbol(selector, Decl(contextuallyTypedJsxChildren2.tsx, 40, 53))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 41, 14))
>State : Symbol(State, Decl(contextuallyTypedJsxChildren2.tsx, 32, 2))
>TSelected : Symbol(TSelected, Decl(contextuallyTypedJsxChildren2.tsx, 40, 26))

children: (state: TSelected) => void
>children : Symbol(children, Decl(contextuallyTypedJsxChildren2.tsx, 41, 40))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 42, 13))
>TSelected : Symbol(TSelected, Decl(contextuallyTypedJsxChildren2.tsx, 40, 26))

}) => React.ReactElement<any>
>React : Symbol(React, Decl(contextuallyTypedJsxChildren2.tsx, 4, 6))
>ReactElement : Symbol(React.ReactElement, Decl(react16.d.ts, 135, 9))

const _result = (
>_result : Symbol(_result, Decl(contextuallyTypedJsxChildren2.tsx, 45, 5))

<Subscribe
>Subscribe : Symbol(Subscribe, Decl(contextuallyTypedJsxChildren2.tsx, 40, 13))

selector={(state) => {
>selector : Symbol(selector, Decl(contextuallyTypedJsxChildren2.tsx, 46, 12))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 47, 15))

return [state.value]
>state.value : Symbol(State.value, Decl(contextuallyTypedJsxChildren2.tsx, 36, 17))
>state : Symbol(state, Decl(contextuallyTypedJsxChildren2.tsx, 47, 15))
>value : Symbol(State.value, Decl(contextuallyTypedJsxChildren2.tsx, 36, 17))

}}
>
{([value = false]) => {
>value : Symbol(value, Decl(contextuallyTypedJsxChildren2.tsx, 51, 7))

console.log(value)
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>value : Symbol(value, Decl(contextuallyTypedJsxChildren2.tsx, 51, 7))

}}
</Subscribe>
>Subscribe : Symbol(Subscribe, Decl(contextuallyTypedJsxChildren2.tsx, 40, 13))

)

Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
//// [tests/cases/compiler/contextuallyTypedJsxChildren2.tsx] ////

=== contextuallyTypedJsxChildren2.tsx ===
/// <reference path="react16.d.ts" />

// https://github.com/microsoft/typescript-go/issues/2802

import * as React from 'react';
>React : typeof React

declare const TestComponentWithChildren: <T, TParam>(props: {
>TestComponentWithChildren : <T, TParam>(props: { state: T; selector?: ((state: NoInfer<T>) => TParam) | undefined; children?: ((state: NoInfer<TParam>) => React.ReactElement<any> | null) | undefined; }) => React.ReactElement<any>
>props : { state: T; selector?: ((state: NoInfer<T>) => TParam) | undefined; children?: ((state: NoInfer<TParam>) => React.ReactElement<any> | null) | undefined; }

state: T;
>state : T

selector?: (state: NoInfer<T>) => TParam;
>selector : ((state: NoInfer<T>) => TParam) | undefined
>state : NoInfer<T>

children?: (state: NoInfer<TParam>) => React.ReactElement<any> | null;
>children : ((state: NoInfer<TParam>) => React.ReactElement<any> | null) | undefined
>state : NoInfer<TParam>
>React : any

}) => React.ReactElement<any>;
>React : any

declare const TestComponentWithoutChildren: <T, TParam>(props: {
>TestComponentWithoutChildren : <T, TParam>(props: { state: T; selector?: ((state: NoInfer<T>) => TParam) | undefined; notChildren?: ((state: NoInfer<TParam>) => React.ReactElement<any> | null) | undefined; }) => React.ReactElement<any>
>props : { state: T; selector?: ((state: NoInfer<T>) => TParam) | undefined; notChildren?: ((state: NoInfer<TParam>) => React.ReactElement<any> | null) | undefined; }

state: T;
>state : T

selector?: (state: NoInfer<T>) => TParam;
>selector : ((state: NoInfer<T>) => TParam) | undefined
>state : NoInfer<T>

notChildren?: (state: NoInfer<TParam>) => React.ReactElement<any> | null;
>notChildren : ((state: NoInfer<TParam>) => React.ReactElement<any> | null) | undefined
>state : NoInfer<TParam>
>React : any

}) => React.ReactElement<any>;
>React : any

const App = () => {
>App : () => JSX.Element
>() => { return ( <> <TestComponentWithChildren state={{ foo: 123 }} selector={(state) => state.foo}> {(selected) => <div>{Math.max(selected, 0)}</div>} </TestComponentWithChildren> <TestComponentWithoutChildren state={{ foo: 123 }} selector={(state) => state.foo} notChildren={(selected) => <div>{Math.max(selected, 0)}</div>} /> </> );} : () => JSX.Element

return (
>( <> <TestComponentWithChildren state={{ foo: 123 }} selector={(state) => state.foo}> {(selected) => <div>{Math.max(selected, 0)}</div>} </TestComponentWithChildren> <TestComponentWithoutChildren state={{ foo: 123 }} selector={(state) => state.foo} notChildren={(selected) => <div>{Math.max(selected, 0)}</div>} /> </> ) : JSX.Element

<>
><> <TestComponentWithChildren state={{ foo: 123 }} selector={(state) => state.foo}> {(selected) => <div>{Math.max(selected, 0)}</div>} </TestComponentWithChildren> <TestComponentWithoutChildren state={{ foo: 123 }} selector={(state) => state.foo} notChildren={(selected) => <div>{Math.max(selected, 0)}</div>} /> </> : JSX.Element

<TestComponentWithChildren state={{ foo: 123 }} selector={(state) => state.foo}>
><TestComponentWithChildren state={{ foo: 123 }} selector={(state) => state.foo}> {(selected) => <div>{Math.max(selected, 0)}</div>} </TestComponentWithChildren> : JSX.Element
>TestComponentWithChildren : <T, TParam>(props: { state: T; selector?: ((state: NoInfer<T>) => TParam) | undefined; children?: ((state: NoInfer<TParam>) => React.ReactElement<any> | null) | undefined; }) => React.ReactElement<any>
>state : { foo: number; }
>{ foo: 123 } : { foo: number; }
>foo : number
>123 : 123
>selector : (state: NoInfer<{ foo: number; }>) => number
>(state) => state.foo : (state: NoInfer<{ foo: number; }>) => number
>state : NoInfer<{ foo: number; }>
>state.foo : number
>state : { foo: number; }
>foo : number

{(selected) => <div>{Math.max(selected, 0)}</div>}
>(selected) => <div>{Math.max(selected, 0)}</div> : (selected: number) => JSX.Element
>selected : number
><div>{Math.max(selected, 0)}</div> : JSX.Element
>div : any
>Math.max(selected, 0) : number
>Math.max : (...values: number[]) => number
>Math : Math
>max : (...values: number[]) => number
>selected : number
>0 : 0
>div : any

</TestComponentWithChildren>
>TestComponentWithChildren : <T, TParam>(props: { state: T; selector?: ((state: NoInfer<T>) => TParam) | undefined; children?: ((state: NoInfer<TParam>) => React.ReactElement<any> | null) | undefined; }) => React.ReactElement<any>

<TestComponentWithoutChildren
><TestComponentWithoutChildren state={{ foo: 123 }} selector={(state) => state.foo} notChildren={(selected) => <div>{Math.max(selected, 0)}</div>} /> : JSX.Element
>TestComponentWithoutChildren : <T, TParam>(props: { state: T; selector?: ((state: NoInfer<T>) => TParam) | undefined; notChildren?: ((state: NoInfer<TParam>) => React.ReactElement<any> | null) | undefined; }) => React.ReactElement<any>

state={{ foo: 123 }}
>state : { foo: number; }
>{ foo: 123 } : { foo: number; }
>foo : number
>123 : 123

selector={(state) => state.foo}
>selector : (state: NoInfer<{ foo: number; }>) => number
>(state) => state.foo : (state: NoInfer<{ foo: number; }>) => number
>state : NoInfer<{ foo: number; }>
>state.foo : number
>state : { foo: number; }
>foo : number

notChildren={(selected) => <div>{Math.max(selected, 0)}</div>}
>notChildren : (selected: number) => JSX.Element
>(selected) => <div>{Math.max(selected, 0)}</div> : (selected: number) => JSX.Element
>selected : number
><div>{Math.max(selected, 0)}</div> : JSX.Element
>div : any
>Math.max(selected, 0) : number
>Math.max : (...values: number[]) => number
>Math : Math
>max : (...values: number[]) => number
>selected : number
>0 : 0
>div : any

/>
</>
);
};

// https://github.com/microsoft/typescript-go/issues/2797

interface State {
value: boolean
>value : boolean
}

declare const Subscribe: <TSelected = State>(props: {
>Subscribe : <TSelected = State>(props: { selector?: ((state: State) => TSelected) | undefined; children: (state: TSelected) => void; }) => React.ReactElement<any>
>props : { selector?: ((state: State) => TSelected) | undefined; children: (state: TSelected) => void; }

selector?: (state: State) => TSelected
>selector : ((state: State) => TSelected) | undefined
>state : State

children: (state: TSelected) => void
>children : (state: TSelected) => void
>state : TSelected

}) => React.ReactElement<any>
>React : any

const _result = (
>_result : JSX.Element
>( <Subscribe selector={(state) => { return [state.value] }} > {([value = false]) => { console.log(value) }} </Subscribe>) : JSX.Element

<Subscribe
><Subscribe selector={(state) => { return [state.value] }} > {([value = false]) => { console.log(value) }} </Subscribe> : JSX.Element
>Subscribe : <TSelected = State>(props: { selector?: ((state: State) => TSelected) | undefined; children: (state: TSelected) => void; }) => React.ReactElement<any>

selector={(state) => {
>selector : (state: State) => boolean[]
>(state) => { return [state.value] } : (state: State) => boolean[]
>state : State

return [state.value]
>[state.value] : boolean[]
>state.value : boolean
>state : State
>value : boolean

}}
>
{([value = false]) => {
>([value = false]) => { console.log(value) } : ([value]: boolean[]) => void
>value : boolean
>false : false

console.log(value)
>console.log(value) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>value : boolean

}}
</Subscribe>
>Subscribe : <TSelected = State>(props: { selector?: ((state: State) => TSelected) | undefined; children: (state: TSelected) => void; }) => React.ReactElement<any>

)

Loading