Skip to content

Commit fbd1338

Browse files
fix(require-explicit-slots): Add support for type reference
1 parent ca7daff commit fbd1338

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

lib/rules/require-explicit-slots.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
'use strict'
66

77
const utils = require('../utils')
8+
const { getComponentPropsFromTypeDefine } = require('../utils/ts-utils')
89

910
/**
1011
* @typedef {import('@typescript-eslint/types').TSESTree.TypeNode} TypeNode
@@ -95,6 +96,32 @@ module.exports = {
9596
slotsDefined.add(slotName)
9697
}
9798
}
99+
} else if (
100+
param.type === 'TSTypeReference' &&
101+
param.typeName.type === 'Identifier'
102+
) {
103+
const componentPropsFromTypeDefine =
104+
getComponentPropsFromTypeDefine(context, typeArguments?.params[0])
105+
106+
for (const memberNode of componentPropsFromTypeDefine) {
107+
const slotName = memberNode.propName
108+
109+
if (!slotName || !memberNode.node) {
110+
continue
111+
}
112+
113+
if (slotsDefined.has(slotName)) {
114+
context.report({
115+
node: memberNode.node,
116+
messageId: 'alreadyDefinedSlot',
117+
data: {
118+
slotName
119+
}
120+
})
121+
} else {
122+
slotsDefined.add(slotName)
123+
}
124+
}
98125
}
99126
}
100127
}),

tests/lib/rules/require-explicit-slots.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,36 @@ tester.run('require-explicit-slots', rule, {
160160
parser: null
161161
}
162162
}
163+
},
164+
{
165+
filename: 'test.vue',
166+
code: `
167+
<template>
168+
<div>
169+
<slot></slot>
170+
</div>
171+
</template>
172+
<script lang="ts" setup>
173+
interface Slots {
174+
default: () => string;
175+
}
176+
defineSlots<Slots>()
177+
</script>`
178+
},
179+
{
180+
filename: 'test.vue',
181+
code: `
182+
<template>
183+
<div>
184+
<slot name="foo"></slot>
185+
</div>
186+
</template>
187+
<script setup lang="ts">
188+
interface MySlots {
189+
foo: (msg: string) => any
190+
}
191+
defineSlots<MySlots>()
192+
</script>`
163193
}
164194
],
165195
invalid: [
@@ -333,6 +363,55 @@ tester.run('require-explicit-slots', rule, {
333363
message: 'Slot foo is already defined.'
334364
}
335365
]
366+
},
367+
{
368+
filename: 'test.vue',
369+
code: `
370+
<template>
371+
<div>
372+
<slot name="foo" />
373+
</div>
374+
</template>
375+
<script setup lang="ts">
376+
interface MySlots {
377+
default: any;
378+
foo: (message: string) => any;
379+
}
380+
defineSlots<MySlots>()
381+
defineSlots<{
382+
default(props: { msg: string }): any,
383+
}>()
384+
</script>`,
385+
errors: [
386+
{
387+
message: 'Slot default is already defined.'
388+
}
389+
]
390+
},
391+
{
392+
filename: 'test.vue',
393+
code: `
394+
<template>
395+
<div>
396+
<slot name="foo" />
397+
</div>
398+
</template>
399+
<script setup lang="ts">
400+
interface MySlots {
401+
default: any;
402+
foo: (message: string) => any;
403+
}
404+
defineSlots<MySlots>()
405+
defineSlots<MySlots>()
406+
</script>`,
407+
errors: [
408+
{
409+
message: 'Slot default is already defined.'
410+
},
411+
{
412+
message: 'Slot foo is already defined.'
413+
}
414+
]
336415
}
337416
]
338417
})

0 commit comments

Comments
 (0)