Skip to content

Commit ddf0b72

Browse files
Fix completions in JSX tag with unstructured spreads (#2335)
1 parent 5756ba1 commit ddf0b72

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package fourslash_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/microsoft/typescript-go/internal/fourslash"
7+
"github.com/microsoft/typescript-go/internal/testutil"
8+
)
9+
10+
func TestCompletionsInJsxTagDifferentSpreadElementTypes(t *testing.T) {
11+
t.Parallel()
12+
13+
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
14+
const content = `
15+
// @Filename: /completionsWithDifferentSpreadTypes.tsx
16+
// @strict: true
17+
18+
// A reasonable type to spread.
19+
export function ComponentObjectX(props: { x: string }) {
20+
return <SomeComponent {...props} /*objectX*//>;
21+
}
22+
23+
// A questionable but valid type to spread.
24+
export function ComponentObjectXOrY(props: { x: string } | { y: string }) {
25+
return <SomeComponent {...props} /*objectXOrY*//>;
26+
}
27+
28+
// A very unexpected type to spread (a union containing a primitive).
29+
export function ComponentNumberOrObjectX(props: number | { x: string }) {
30+
return <SomeComponent {...props} /*numberOrObjectX*//>;
31+
}
32+
33+
// Very unexpected, but still structured (union) types.
34+
// 'boolean' is 'true | false' and an optional 'null' is really 'null | undefined'.
35+
export function ComponentBoolean(props: boolean) {
36+
return <SomeComponent {...props} /*boolean*//>;
37+
}
38+
export function ComponentOptionalNull(props?: null) {
39+
return <SomeComponent {...props} /*optNull*//>;
40+
}
41+
42+
// Primitive types (non-structured).
43+
export function ComponentAny(props: any) {
44+
return <SomeComponent {...props} /*any*//>;
45+
}
46+
export function ComponentUnknown(props: unknown) {
47+
return <SomeComponent {...props} /*unknown*//>;
48+
}
49+
export function ComponentNever(props: never) {
50+
return <SomeComponent {...props} /*never*//>;
51+
}
52+
export function ComponentUndefined(props: undefined) {
53+
return <SomeComponent {...props} /*undefined*//>;
54+
}
55+
export function ComponentNumber(props: number) {
56+
return <SomeComponent {...props} /*number*//>;
57+
}
58+
`
59+
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
60+
defer done()
61+
f.GoToEachMarker(t, nil, func(marker *fourslash.Marker, index int) {
62+
f.VerifyCompletions(t, marker, nil)
63+
})
64+
}

internal/ls/completions.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4079,7 +4079,7 @@ func setMemberDeclaredBySpreadAssignment(declaration *ast.Node, members *collect
40794079
t = typeChecker.GetTypeOfSymbolAtLocation(symbol, expression)
40804080
}
40814081
var properties []*ast.Symbol
4082-
if t != nil {
4082+
if t != nil && t.Flags()&checker.TypeFlagsStructuredType != 0 {
40834083
properties = t.AsStructuredType().Properties()
40844084
}
40854085
for _, property := range properties {

0 commit comments

Comments
 (0)