Skip to content

Commit d7d0e0e

Browse files
danyadevdanil.nemov
authored and
danil.nemov
committed
fix(types): make generics with runtime props in defineComponent work
1 parent d0253a0 commit d7d0e0e

File tree

2 files changed

+90
-12
lines changed

2 files changed

+90
-12
lines changed

packages-private/dts-test/defineComponent.test-d.tsx

+88-11
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,7 @@ describe('function syntax w/ emits', () => {
13731373
describe('function syntax w/ runtime props', () => {
13741374
// with runtime props, the runtime props must match
13751375
// manual type declaration
1376-
defineComponent(
1376+
const Comp1 = defineComponent(
13771377
(_props: { msg: string }) => {
13781378
return () => {}
13791379
},
@@ -1382,7 +1382,34 @@ describe('function syntax w/ runtime props', () => {
13821382
},
13831383
)
13841384

1385+
// @ts-expect-error bar isn't specified in props definition
13851386
defineComponent(
1387+
(_props: { msg: string }) => {
1388+
return () => {}
1389+
},
1390+
{
1391+
props: ['msg', 'bar'],
1392+
},
1393+
)
1394+
1395+
defineComponent(
1396+
(_props: { msg: string; bar: string }) => {
1397+
return () => {}
1398+
},
1399+
{
1400+
props: ['msg'],
1401+
},
1402+
)
1403+
1404+
expectType<JSX.Element>(<Comp1 msg="1" />)
1405+
// @ts-expect-error msg type is incorrect
1406+
expectType<JSX.Element>(<Comp1 msg={1} />)
1407+
// @ts-expect-error msg is missing
1408+
expectType<JSX.Element>(<Comp1 />)
1409+
// @ts-expect-error bar doesn't exist
1410+
expectType<JSX.Element>(<Comp1 msg="1" bar="2" />)
1411+
1412+
const Comp2 = defineComponent(
13861413
<T extends string>(_props: { msg: T }) => {
13871414
return () => {}
13881415
},
@@ -1391,7 +1418,36 @@ describe('function syntax w/ runtime props', () => {
13911418
},
13921419
)
13931420

1421+
// @ts-expect-error bar isn't specified in props definition
13941422
defineComponent(
1423+
<T extends string>(_props: { msg: T }) => {
1424+
return () => {}
1425+
},
1426+
{
1427+
props: ['msg', 'bar'],
1428+
},
1429+
)
1430+
1431+
defineComponent(
1432+
<T extends string>(_props: { msg: T; bar: T }) => {
1433+
return () => {}
1434+
},
1435+
{
1436+
props: ['msg'],
1437+
},
1438+
)
1439+
1440+
expectType<JSX.Element>(<Comp2 msg="1" />)
1441+
expectType<JSX.Element>(<Comp2<string> msg="1" />)
1442+
// @ts-expect-error msg type is incorrect
1443+
expectType<JSX.Element>(<Comp2 msg={1} />)
1444+
// @ts-expect-error msg is missing
1445+
expectType<JSX.Element>(<Comp2 />)
1446+
// @ts-expect-error bar doesn't exist
1447+
expectType<JSX.Element>(<Comp2 msg="1" bar="2" />)
1448+
1449+
// Note: generics aren't supported with object runtime props
1450+
const Comp3 = defineComponent(
13951451
<T extends string>(_props: { msg: T }) => {
13961452
return () => {}
13971453
},
@@ -1402,37 +1458,58 @@ describe('function syntax w/ runtime props', () => {
14021458
},
14031459
)
14041460

1405-
// @ts-expect-error string prop names don't match
14061461
defineComponent(
1407-
(_props: { msg: string }) => {
1462+
// @ts-expect-error bar isn't specified in props definition
1463+
<T extends string>(_props: { msg: T }) => {
14081464
return () => {}
14091465
},
14101466
{
1411-
props: ['bar'],
1467+
props: {
1468+
bar: String,
1469+
},
14121470
},
14131471
)
14141472

14151473
defineComponent(
1416-
(_props: { msg: string }) => {
1474+
// @ts-expect-error generics aren't supported with object runtime props
1475+
<T extends string>(_props: { msg: T; bar: T }) => {
14171476
return () => {}
14181477
},
14191478
{
14201479
props: {
1421-
// @ts-expect-error prop type mismatch
1422-
msg: Number,
1480+
msg: String,
14231481
},
14241482
},
14251483
)
14261484

1427-
// @ts-expect-error prop keys don't match
1485+
expectType<JSX.Element>(<Comp3 msg="1" />)
1486+
// @ts-expect-error generics aren't supported with object runtime props
1487+
expectType<JSX.Element>(<Comp3<string> msg="1" />)
1488+
// @ts-expect-error msg type is incorrect
1489+
expectType<JSX.Element>(<Comp3 msg={1} />)
1490+
// @ts-expect-error msg is missing
1491+
expectType<JSX.Element>(<Comp3 />)
1492+
// @ts-expect-error bar doesn't exist
1493+
expectType<JSX.Element>(<Comp3 msg="1" bar="2" />)
1494+
1495+
// @ts-expect-error string prop names don't match
14281496
defineComponent(
1429-
(_props: { msg: string }, ctx) => {
1497+
(_props: { msg: string }) => {
1498+
return () => {}
1499+
},
1500+
{
1501+
props: ['bar'],
1502+
},
1503+
)
1504+
1505+
defineComponent(
1506+
(_props: { msg: string }) => {
14301507
return () => {}
14311508
},
14321509
{
14331510
props: {
1434-
msg: String,
1435-
bar: String,
1511+
// @ts-expect-error prop type mismatch
1512+
msg: Number,
14361513
},
14371514
},
14381515
)

packages/runtime-core/src/apiDefineComponent.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,14 @@ export function defineComponent<
151151
E extends EmitsOptions = {},
152152
EE extends string = string,
153153
S extends SlotsType = {},
154+
DeclaredProps extends (keyof Props)[] = (keyof Props)[],
154155
>(
155156
setup: (
156157
props: Props,
157158
ctx: SetupContext<E, S>,
158159
) => RenderFunction | Promise<RenderFunction>,
159160
options?: Pick<ComponentOptions, 'name' | 'inheritAttrs'> & {
160-
props?: (keyof Props)[]
161+
props?: DeclaredProps
161162
emits?: E | EE[]
162163
slots?: S
163164
},

0 commit comments

Comments
 (0)