Skip to content

Commit 4d2388d

Browse files
committed
feat: detect ts as expression and Vue's PropType
1 parent 0f20817 commit 4d2388d

File tree

4 files changed

+30
-2
lines changed

4 files changed

+30
-2
lines changed

src/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export interface ComponentPropType {
22
type: string
3+
elementType?: string
34
}
45

56
export interface ComponentProp {

src/utils/parseSetupScript.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ export function parseSetupScript (id: string, descriptor: SFCDescriptor) {
1919
return prop.name
2020
}
2121

22+
if (prop.type === 'TSAsExpression') {
23+
return getType(prop.typeAnnotation)
24+
}
25+
2226
if (prop.type === 'ObjectExpression') {
2327
return prop.properties.reduce((acc, prop) => {
2428
acc[prop.key.name] = getValue(prop.value)
@@ -27,7 +31,7 @@ export function parseSetupScript (id: string, descriptor: SFCDescriptor) {
2731
}
2832
}
2933
function getType (tsProperty) {
30-
const { type, typeName, elementType } = tsProperty.typeAnnotation?.typeAnnotation || tsProperty
34+
const { type, typeName, elementType, typeParameters } = tsProperty.typeAnnotation?.typeAnnotation || tsProperty
3135
switch (type) {
3236
case 'TSStringKeyword':
3337
return 'String'
@@ -38,6 +42,15 @@ export function parseSetupScript (id: string, descriptor: SFCDescriptor) {
3842
case 'TSObjectKeyword':
3943
return 'Object'
4044
case 'TSTypeReference':
45+
if (typeParameters?.params) {
46+
if (typeName.name === 'PropType') {
47+
return getType(typeParameters.params[0])
48+
}
49+
return {
50+
type: typeName.name,
51+
elementType: typeParameters.params.map(type => getType(type))
52+
}
53+
}
4154
return typeName.name
4255
case 'TSArrayType':
4356
return {

test/basic-component.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import fsp from 'fs/promises'
22
import { fileURLToPath } from 'url'
33
import { test, describe, expect } from 'vitest'
4+
import { ComponentPropType } from '../src/types'
45
import { parseComponent } from '../src/utils/parseComponent'
56

67
describe('Basic Component', async () => {
@@ -52,6 +53,12 @@ describe('Basic Component', async () => {
5253

5354
expect(arrayProps.length).toBe(1)
5455
expect(arrayProps[0].name).toBe('arrayProp')
56+
57+
const typedArrayProps = props.filter(p => (p.type as ComponentPropType)?.type === 'Array')
58+
59+
expect(typedArrayProps.length).toBe(1)
60+
expect(typedArrayProps[0].name).toBe('typedArrayProps')
61+
expect((typedArrayProps[0].type as ComponentPropType).elementType).toBe('String')
5562
})
5663

5764
test('Object', () => {

test/fixtures/basic/components/BasicComponent.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
</div>
1010
</template>
1111

12-
<script setup>
12+
<script setup lang="ts">
13+
import type { PropType } from 'vue'
14+
1315
const props = defineProps({
1416
stringProp: {
1517
type: String,
@@ -27,6 +29,11 @@ const props = defineProps({
2729
type: Array,
2830
default: () => []
2931
},
32+
typedArrayProps: {
33+
type: Array as PropType<string[]>,
34+
default: () => ([]),
35+
required: false
36+
},
3037
objectProp: {
3138
type: Object,
3239
default: () => ({})

0 commit comments

Comments
 (0)