mirror of https://github.com/vuejs/core.git
parent
83661264a4
commit
10d34a5624
|
@ -447,6 +447,42 @@ describe('resolveType', () => {
|
|||
})
|
||||
})
|
||||
|
||||
test('keyof', () => {
|
||||
const files = {
|
||||
'/foo.ts': `export type IMP = { ${1}: 1 };`,
|
||||
}
|
||||
|
||||
const { props } = resolve(
|
||||
`
|
||||
import { IMP } from './foo'
|
||||
interface Foo { foo: 1, ${1}: 1 }
|
||||
type Bar = { bar: 1 }
|
||||
declare const obj: Bar
|
||||
declare const set: Set<any>
|
||||
declare const arr: Array<any>
|
||||
|
||||
defineProps<{
|
||||
imp: keyof IMP,
|
||||
foo: keyof Foo,
|
||||
bar: keyof Bar,
|
||||
obj: keyof typeof obj,
|
||||
set: keyof typeof set,
|
||||
arr: keyof typeof arr
|
||||
}>()
|
||||
`,
|
||||
files,
|
||||
)
|
||||
|
||||
expect(props).toStrictEqual({
|
||||
imp: ['Number'],
|
||||
foo: ['String', 'Number'],
|
||||
bar: ['String'],
|
||||
obj: ['String'],
|
||||
set: ['String'],
|
||||
arr: ['String', 'Number'],
|
||||
})
|
||||
})
|
||||
|
||||
test('ExtractPropTypes (element-plus)', () => {
|
||||
const { props, raw } = resolve(
|
||||
`
|
||||
|
|
|
@ -1448,6 +1448,7 @@ export function inferRuntimeType(
|
|||
ctx: TypeResolveContext,
|
||||
node: Node & MaybeWithScope,
|
||||
scope = node._ownerScope || ctxToScope(ctx),
|
||||
isKeyOf = false,
|
||||
): string[] {
|
||||
try {
|
||||
switch (node.type) {
|
||||
|
@ -1467,8 +1468,18 @@ export function inferRuntimeType(
|
|||
const types = new Set<string>()
|
||||
const members =
|
||||
node.type === 'TSTypeLiteral' ? node.members : node.body.body
|
||||
|
||||
for (const m of members) {
|
||||
if (
|
||||
if (isKeyOf) {
|
||||
if (
|
||||
m.type === 'TSPropertySignature' &&
|
||||
m.key.type === 'NumericLiteral'
|
||||
) {
|
||||
types.add('Number')
|
||||
} else {
|
||||
types.add('String')
|
||||
}
|
||||
} else if (
|
||||
m.type === 'TSCallSignatureDeclaration' ||
|
||||
m.type === 'TSConstructSignatureDeclaration'
|
||||
) {
|
||||
|
@ -1477,6 +1488,7 @@ export function inferRuntimeType(
|
|||
types.add('Object')
|
||||
}
|
||||
}
|
||||
|
||||
return types.size ? Array.from(types) : ['Object']
|
||||
}
|
||||
case 'TSPropertySignature':
|
||||
|
@ -1512,9 +1524,22 @@ export function inferRuntimeType(
|
|||
case 'TSTypeReference': {
|
||||
const resolved = resolveTypeReference(ctx, node, scope)
|
||||
if (resolved) {
|
||||
return inferRuntimeType(ctx, resolved, resolved._ownerScope)
|
||||
return inferRuntimeType(ctx, resolved, resolved._ownerScope, isKeyOf)
|
||||
}
|
||||
|
||||
if (node.typeName.type === 'Identifier') {
|
||||
if (isKeyOf) {
|
||||
switch (node.typeName.name) {
|
||||
case 'String':
|
||||
case 'Array':
|
||||
case 'ArrayLike':
|
||||
case 'ReadonlyArray':
|
||||
return ['String', 'Number']
|
||||
default:
|
||||
return ['String']
|
||||
}
|
||||
}
|
||||
|
||||
switch (node.typeName.name) {
|
||||
case 'Array':
|
||||
case 'Function':
|
||||
|
@ -1634,7 +1659,7 @@ export function inferRuntimeType(
|
|||
// typeof only support identifier in local scope
|
||||
const matched = scope.declares[id.name]
|
||||
if (matched) {
|
||||
return inferRuntimeType(ctx, matched, matched._ownerScope)
|
||||
return inferRuntimeType(ctx, matched, matched._ownerScope, isKeyOf)
|
||||
}
|
||||
}
|
||||
break
|
||||
|
@ -1642,7 +1667,12 @@ export function inferRuntimeType(
|
|||
|
||||
// e.g. readonly
|
||||
case 'TSTypeOperator': {
|
||||
return inferRuntimeType(ctx, node.typeAnnotation, scope)
|
||||
return inferRuntimeType(
|
||||
ctx,
|
||||
node.typeAnnotation,
|
||||
scope,
|
||||
node.operator === 'keyof',
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
Loading…
Reference in New Issue