Skip to content

Commit 46e3374

Browse files
authoredNov 10, 2023
fix(types): more precise types for class bindings (#8012)
1 parent fa65cb6 commit 46e3374

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed
 

‎packages/dts-test/tsx.test-d.tsx

+36
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,42 @@ expectType<JSX.Element>(
1717
<div style={[{ color: 'red' }, [{ fontSize: '1em' }]]} />
1818
)
1919

20+
// allow undefined, string, object, array and nested array classes
21+
expectType<JSX.Element>(<div class={undefined} />)
22+
expectType<JSX.Element>(<div class={'foo'} />)
23+
expectType<JSX.Element>(<div class={['foo', undefined, 'bar']} />)
24+
expectType<JSX.Element>(<div class={[]} />)
25+
expectType<JSX.Element>(<div class={['foo', ['bar'], [['baz']]]} />)
26+
expectType<JSX.Element>(<div class={{ foo: true, bar: false, baz: true }} />)
27+
expectType<JSX.Element>(<div class={{}} />)
28+
expectType<JSX.Element>(
29+
<div class={['foo', ['bar'], { baz: true }, [{ qux: true }]]} />
30+
)
31+
expectType<JSX.Element>(
32+
<div
33+
class={[
34+
{ foo: false },
35+
{ bar: 0 },
36+
{ baz: -0 },
37+
{ qux: '' },
38+
{ quux: null },
39+
{ corge: undefined },
40+
{ grault: NaN }
41+
]}
42+
/>
43+
)
44+
expectType<JSX.Element>(
45+
<div
46+
class={[
47+
{ foo: true },
48+
{ bar: 'not-empty' },
49+
{ baz: 1 },
50+
{ qux: {} },
51+
{ quux: [] }
52+
]}
53+
/>
54+
)
55+
2056
// #7955
2157
expectType<JSX.Element>(<div style={[undefined, '', null, false]} />)
2258

‎packages/runtime-dom/src/jsx.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -252,10 +252,16 @@ export type StyleValue =
252252
| CSSProperties
253253
| Array<StyleValue>
254254

255+
export type ClassValue =
256+
| undefined
257+
| string
258+
| Record<string | number, unknown>
259+
| Array<ClassValue>
260+
255261
export interface HTMLAttributes extends AriaAttributes, EventHandlers<Events> {
256262
innerHTML?: string
257263

258-
class?: any
264+
class?: ClassValue
259265
style?: StyleValue
260266

261267
// Standard HTML Attributes

‎packages/shared/__tests__/normalizeProp.spec.ts

+48
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { normalizeClass, parseStringStyle } from '../src'
22

33
describe('normalizeClass', () => {
4+
test('handles undefined correctly', () => {
5+
expect(normalizeClass(undefined)).toEqual('')
6+
})
7+
48
test('handles string correctly', () => {
59
expect(normalizeClass('foo')).toEqual('foo')
610
})
@@ -11,12 +15,56 @@ describe('normalizeClass', () => {
1115
)
1216
})
1317

18+
test('handles empty array correctly', () => {
19+
expect(normalizeClass([])).toEqual('')
20+
})
21+
22+
test('handles nested array correctly', () => {
23+
expect(normalizeClass(['foo', ['bar'], [['baz']]])).toEqual('foo bar baz')
24+
})
25+
1426
test('handles object correctly', () => {
1527
expect(normalizeClass({ foo: true, bar: false, baz: true })).toEqual(
1628
'foo baz'
1729
)
1830
})
1931

32+
test('handles empty object correctly', () => {
33+
expect(normalizeClass({})).toEqual('')
34+
})
35+
36+
test('handles arrays and objects correctly', () => {
37+
expect(
38+
normalizeClass(['foo', ['bar'], { baz: true }, [{ qux: true }]])
39+
).toEqual('foo bar baz qux')
40+
})
41+
42+
test('handles array of objects with falsy values', () => {
43+
expect(
44+
normalizeClass([
45+
{ foo: false },
46+
{ bar: 0 },
47+
{ baz: -0 },
48+
{ qux: '' },
49+
{ quux: null },
50+
{ corge: undefined },
51+
{ grault: NaN }
52+
])
53+
).toEqual('')
54+
})
55+
56+
test('handles array of objects with truthy values', () => {
57+
expect(
58+
normalizeClass([
59+
{ foo: true },
60+
{ bar: 'not-empty' },
61+
{ baz: 1 },
62+
{ qux: {} },
63+
{ quux: [] }
64+
])
65+
).toEqual('foo bar baz qux quux')
66+
})
67+
2068
// #6777
2169
test('parse multi-line inline style', () => {
2270
expect(

0 commit comments

Comments
 (0)
Please sign in to comment.