Skip to content

Commit 1b69d5f

Browse files
authored
fix(compiler-sfc): unwrap TS node for defineProps (#7340)
1 parent 6391daf commit 1b69d5f

File tree

4 files changed

+62
-16
lines changed

4 files changed

+62
-16
lines changed

packages/compiler-core/src/babelUtils.ts

+16-3
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@ export function walkIdentifiers(
3838
if (
3939
parent &&
4040
parent.type.startsWith('TS') &&
41-
parent.type !== 'TSAsExpression' &&
42-
parent.type !== 'TSNonNullExpression' &&
43-
parent.type !== 'TSTypeAssertion'
41+
!TS_NODE_TYPES.includes(parent.type)
4442
) {
4543
return this.skip()
4644
}
@@ -422,3 +420,18 @@ function isReferenced(node: Node, parent: Node, grandparent?: Node): boolean {
422420

423421
return true
424422
}
423+
424+
export const TS_NODE_TYPES = [
425+
'TSAsExpression', // foo as number
426+
'TSTypeAssertion', // (<number>foo)
427+
'TSNonNullExpression', // foo!
428+
'TSInstantiationExpression', // foo<string>
429+
'TSSatisfiesExpression' // foo satisfies T
430+
]
431+
export function unwrapTSNode(node: Node): Node {
432+
if (TS_NODE_TYPES.includes(node.type)) {
433+
return unwrapTSNode((node as any).expression)
434+
} else {
435+
return node
436+
}
437+
}

packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap

+16
Original file line numberDiff line numberDiff line change
@@ -1486,6 +1486,22 @@ return { emit }
14861486
})"
14871487
`;
14881488

1489+
exports[`SFC compile <script setup> > with TypeScript > defineProps w/ TS assertion 1`] = `
1490+
"import { defineComponent as _defineComponent } from 'vue'
1491+
1492+
export default /*#__PURE__*/_defineComponent({
1493+
props: ['foo'],
1494+
setup(__props, { expose }) {
1495+
expose();
1496+
1497+
1498+
1499+
return { }
1500+
}
1501+
1502+
})"
1503+
`;
1504+
14891505
exports[`SFC compile <script setup> > with TypeScript > defineProps w/ exported interface 1`] = `
14901506
"import { defineComponent as _defineComponent } from 'vue'
14911507
export interface Props { x?: number }

packages/compiler-sfc/__tests__/compileScript.spec.ts

+13
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,19 @@ const emit = defineEmits(['a', 'b'])
11451145
})
11461146
})
11471147

1148+
test('defineProps w/ TS assertion', () => {
1149+
const { content, bindings } = compile(`
1150+
<script setup lang="ts">
1151+
defineProps(['foo'])! as any
1152+
</script>
1153+
`)
1154+
expect(content).toMatch(`props: ['foo']`)
1155+
assertCode(content)
1156+
expect(bindings).toStrictEqual({
1157+
foo: BindingTypes.PROPS
1158+
})
1159+
})
1160+
11481161
test('withDefaults (static)', () => {
11491162
const { content, bindings } = compile(`
11501163
<script setup lang="ts">

packages/compiler-sfc/src/compileScript.ts

+17-13
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import {
99
UNREF,
1010
SimpleExpressionNode,
1111
isFunctionType,
12-
walkIdentifiers
12+
walkIdentifiers,
13+
unwrapTSNode
1314
} from '@vue/compiler-dom'
1415
import { DEFAULT_FILENAME, SFCDescriptor, SFCScriptBlock } from './parse'
1516
import {
@@ -1229,17 +1230,18 @@ export function compileScript(
12291230
}
12301231

12311232
if (node.type === 'ExpressionStatement') {
1233+
const expr = unwrapTSNode(node.expression)
12321234
// process `defineProps` and `defineEmit(s)` calls
12331235
if (
1234-
processDefineProps(node.expression) ||
1235-
processDefineEmits(node.expression) ||
1236-
processDefineOptions(node.expression) ||
1237-
processWithDefaults(node.expression)
1236+
processDefineProps(expr) ||
1237+
processDefineEmits(expr) ||
1238+
processDefineOptions(expr) ||
1239+
processWithDefaults(expr)
12381240
) {
12391241
s.remove(node.start! + startOffset, node.end! + startOffset)
1240-
} else if (processDefineExpose(node.expression)) {
1242+
} else if (processDefineExpose(expr)) {
12411243
// defineExpose({}) -> expose({})
1242-
const callee = (node.expression as CallExpression).callee
1244+
const callee = (expr as CallExpression).callee
12431245
s.overwrite(
12441246
callee.start! + startOffset,
12451247
callee.end! + startOffset,
@@ -1253,8 +1255,9 @@ export function compileScript(
12531255
let left = total
12541256
for (let i = 0; i < total; i++) {
12551257
const decl = node.declarations[i]
1256-
if (decl.init) {
1257-
if (processDefineOptions(decl.init)) {
1258+
const init = decl.init && unwrapTSNode(decl.init)
1259+
if (init) {
1260+
if (processDefineOptions(init)) {
12581261
error(
12591262
`${DEFINE_OPTIONS}() has no returning value, it cannot be assigned.`,
12601263
node
@@ -1263,9 +1266,9 @@ export function compileScript(
12631266

12641267
// defineProps / defineEmits
12651268
const isDefineProps =
1266-
processDefineProps(decl.init, decl.id, node.kind) ||
1267-
processWithDefaults(decl.init, decl.id, node.kind)
1268-
const isDefineEmits = processDefineEmits(decl.init, decl.id)
1269+
processDefineProps(init, decl.id, node.kind) ||
1270+
processWithDefaults(init, decl.id, node.kind)
1271+
const isDefineEmits = processDefineEmits(init, decl.id)
12691272
if (isDefineProps || isDefineEmits) {
12701273
if (left === 1) {
12711274
s.remove(node.start! + startOffset, node.end! + startOffset)
@@ -1801,7 +1804,8 @@ function walkDeclaration(
18011804
)
18021805

18031806
// export const foo = ...
1804-
for (const { id, init } of node.declarations) {
1807+
for (const { id, init: _init } of node.declarations) {
1808+
const init = _init && unwrapTSNode(_init)
18051809
const isDefineCall = !!(
18061810
isConst &&
18071811
isCallOf(

0 commit comments

Comments
 (0)