Skip to content

Commit 075498c

Browse files
committed
refactor: avoid hard error when inferring runtime type
1 parent a9f5e14 commit 075498c

File tree

4 files changed

+35
-8
lines changed

4 files changed

+35
-8
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,11 @@ describe('resolveType', () => {
397397
resolve(`import { X } from './foo'; defineProps<X>()`)
398398
).toThrow(`Failed to resolve import source "./foo" for type X`)
399399
})
400+
401+
test('should not error on unresolved type when inferring runtime type', () => {
402+
expect(() => resolve(`defineProps<{ foo: T }>()`)).not.toThrow()
403+
expect(() => resolve(`defineProps<{ foo: T['bar'] }>()`)).not.toThrow()
404+
})
400405
})
401406
})
402407

packages/compiler-sfc/src/parse.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ export interface SFCScriptBlock extends SFCBlock {
4747
imports?: Record<string, ImportBinding>
4848
scriptAst?: import('@babel/types').Statement[]
4949
scriptSetupAst?: import('@babel/types').Statement[]
50+
warnings?: string[]
51+
/**
52+
* Fully resolved dependency file paths (unix slashes) with imported types
53+
* used in macros, used for HMR cache busting in @vitejs/plugin-vue and
54+
* vue-loader.
55+
*/
56+
deps?: string[]
5057
}
5158

5259
export interface SFCStyleBlock extends SFCBlock {

packages/compiler-sfc/src/script/context.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { PropsDestructureBindings } from './defineProps'
77
import { ModelDecl } from './defineModel'
88
import { BindingMetadata } from '../../../compiler-core/src'
99
import MagicString from 'magic-string'
10-
import { TypeScope, WithScope } from './resolveType'
10+
import { TypeScope } from './resolveType'
1111

1212
export class ScriptCompileContext {
1313
isJS: boolean
@@ -56,13 +56,17 @@ export class ScriptCompileContext {
5656

5757
// codegen
5858
bindingMetadata: BindingMetadata = {}
59-
6059
helperImports: Set<string> = new Set()
6160
helper(key: string): string {
6261
this.helperImports.add(key)
6362
return `_${key}`
6463
}
6564

65+
/**
66+
* to be exposed on compiled script block for HMR cache busting
67+
*/
68+
deps?: string[]
69+
6670
constructor(
6771
public descriptor: SFCDescriptor,
6872
public options: SFCScriptCompileOptions
@@ -125,7 +129,7 @@ export class ScriptCompileContext {
125129
return block.content.slice(node.start!, node.end!)
126130
}
127131

128-
error(msg: string, node: Node & WithScope, scope?: TypeScope): never {
132+
error(msg: string, node: Node, scope?: TypeScope): never {
129133
const offset = scope ? scope.offset : this.startOffset!
130134
throw new Error(
131135
`[@vue/compiler-sfc] ${msg}\n\n${

packages/compiler-sfc/src/script/resolveType.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ function innerResolveTypeElements(
134134
break
135135
}
136136
} else {
137+
// TODO support `number` and `string` index type when possible
137138
ctx.error(
138139
`Unsupported index type: ${node.indexType.type}`,
139140
node.indexType,
@@ -320,7 +321,11 @@ function resolveStringType(
320321
case 'Uncapitalize':
321322
return getParam().map(s => s[0].toLowerCase() + s.slice(1))
322323
default:
323-
ctx.error('Failed to resolve type reference', node, scope)
324+
ctx.error(
325+
'Unsupported type when resolving string type',
326+
node.typeName,
327+
scope
328+
)
324329
}
325330
}
326331
}
@@ -906,7 +911,7 @@ export function inferRuntimeType(
906911
if (node.typeName.type === 'Identifier') {
907912
const resolved = resolveTypeReference(ctx, node, scope)
908913
if (resolved) {
909-
return inferRuntimeType(ctx, resolved, scope)
914+
return inferRuntimeType(ctx, resolved, resolved._ownerScope)
910915
}
911916
switch (node.typeName.name) {
912917
case 'Array':
@@ -988,9 +993,15 @@ export function inferRuntimeType(
988993
node.indexType.type === 'TSLiteralType' &&
989994
node.indexType.literal.type === 'StringLiteral'
990995
) {
991-
const resolved = resolveTypeElements(ctx, node.objectType)
992-
const key = node.indexType.literal.value
993-
return inferRuntimeType(ctx, resolved.props[key])
996+
try {
997+
const resolved = resolveTypeElements(ctx, node.objectType, scope)
998+
const key = node.indexType.literal.value
999+
const prop = resolved.props[key]
1000+
return inferRuntimeType(ctx, prop, prop._ownerScope)
1001+
} catch (e) {
1002+
// avoid hard error, fallback to unknown
1003+
return [UNKNOWN_TYPE]
1004+
}
9941005
}
9951006
}
9961007

0 commit comments

Comments
 (0)