From 48fd3e4c787d2e080a67d3c736298111bc2e318e Mon Sep 17 00:00:00 2001 From: Johnson Chu Date: Mon, 15 Dec 2025 17:33:23 +0800 Subject: [PATCH 1/5] refactor(component-meta): remove vue-component-type-helpers --- packages/component-meta/lib/base.ts | 176 +++++------------- packages/component-meta/lib/helpers.ts | 153 +++++++++++++++ packages/component-meta/package.json | 3 +- .../language-core/lib/parsers/scriptRanges.ts | 2 +- pnpm-lock.yaml | 3 - 5 files changed, 202 insertions(+), 135 deletions(-) create mode 100644 packages/component-meta/lib/helpers.ts diff --git a/packages/component-meta/lib/base.ts b/packages/component-meta/lib/base.ts index 70ad4ff6c0..809ed9bf6d 100644 --- a/packages/component-meta/lib/base.ts +++ b/packages/component-meta/lib/base.ts @@ -2,6 +2,13 @@ import { createLanguageServiceHost, resolveFileLanguageId, type TypeScriptProjec import * as core from '@vue/language-core'; import { posix as path } from 'path-browserify'; import type * as ts from 'typescript'; +import { + inferComponentEmit, + inferComponentExposed, + inferComponentProps, + inferComponentSlots, + inferComponentType, +} from './helpers'; import type { ComponentMeta, @@ -105,23 +112,14 @@ function baseCreate( getCurrentDirectory: () => rootPath, getProjectVersion: () => projectVersion.toString(), getCompilationSettings: () => options, - getScriptFileNames: () => [...fileNamesSet], + getScriptFileNames: () => [ + ...[...fileNamesSet], + globalComponentName, + ], getProjectReferences: () => projectReferences, }; const globalComponentSnapshot = ts.ScriptSnapshot.fromString(''); const scriptSnapshots = new Map(); - const metaSnapshots = new Map(); - const getScriptFileNames = projectHost.getScriptFileNames; - projectHost.getScriptFileNames = () => { - const names = getScriptFileNames(); - return [ - ...names, - ...names.map(getMetaFileName), - globalComponentName, - getMetaFileName(globalComponentName), - ]; - }; - const vueLanguagePlugin = core.createVueLanguagePlugin( ts, projectHost.getCompilationSettings(), @@ -144,12 +142,6 @@ function baseCreate( if (fileName === globalComponentName) { snapshot = globalComponentSnapshot; } - else if (isMetaFileName(fileName)) { - if (!metaSnapshots.has(fileName)) { - metaSnapshots.set(fileName, ts.ScriptSnapshot.fromString(getMetaScriptContent(fileName))); - } - snapshot = metaSnapshots.get(fileName); - } else { if (!scriptSnapshots.has(fileName)) { const fileText = ts.sys.readFile(fileName); @@ -222,59 +214,36 @@ function baseCreate( }, }; - function isMetaFileName(fileName: string) { - return fileName.endsWith('.meta.ts'); - } - - function getMetaFileName(fileName: string) { - return ( - vueOptions.extensions.some(ext => fileName.endsWith(ext)) - ? fileName - : fileName.slice(0, fileName.lastIndexOf('.')) - ) + '.meta.ts'; - } - - function getMetaScriptContent(fileName: string) { - const helpersPath = require.resolve('vue-component-type-helpers').replace(windowsPathReg, '/'); - let helpersRelativePath = path.relative(path.dirname(fileName), helpersPath); - if (!helpersRelativePath.startsWith('./') && !helpersRelativePath.startsWith('../')) { - helpersRelativePath = './' + helpersRelativePath; - } - let code = ` -import type { ComponentType, ComponentProps, ComponentEmit, ComponentSlots, ComponentExposed } from '${helpersRelativePath}'; -import type * as Components from '${fileName.slice(0, -'.meta.ts'.length)}'; - -export default {} as { [K in keyof typeof Components]: ComponentMeta; }; - -interface ComponentMeta { - type: ComponentType; - props: ComponentProps; - emit: ComponentEmit; - slots: ComponentSlots; - exposed: ComponentExposed; -} -`.trim(); - return code; - } - function getExportNames(componentPath: string) { const program = tsLs.getProgram()!; - const typeChecker = program.getTypeChecker(); - return _getExports(program, typeChecker, componentPath).exports.map(e => e.getName()); + const sourceFile = program.getSourceFile(componentPath); + if (sourceFile) { + const scriptRanges = getScriptRanges(sourceFile); + return Object.keys(scriptRanges.exports); + } } function getComponentMeta(componentPath: string, exportName = 'default'): ComponentMeta { - const program = tsLs.getProgram()!; - const typeChecker = program.getTypeChecker(); - const { symbolNode, exports } = _getExports(program, typeChecker, componentPath); - const _export = exports.find(property => property.getName() === exportName); + let program = tsLs.getProgram()!; + let sourceFile = program.getSourceFile(componentPath); + if (!sourceFile) { + fileNamesSet.add(componentPath); + projectVersion++; + program = tsLs.getProgram()!; + sourceFile = program.getSourceFile(componentPath); + if (!sourceFile) { + throw `Could not find component file: ${componentPath}`; + } + } - if (!_export) { + const scriptRanges = getScriptRanges(sourceFile); + const component = scriptRanges.exports[exportName]; + if (!component) { throw `Could not find export ${exportName}`; } - const componentType = typeChecker.getTypeOfSymbolAtLocation(_export, symbolNode); - const symbolProperties = componentType.getProperties(); + const symbolNode = component.expression.node; + const typeChecker = program.getTypeChecker(); let _type: ReturnType | undefined; let _props: ReturnType | undefined; @@ -311,24 +280,16 @@ interface ComponentMeta { return meta; function getType() { - const $type = symbolProperties.find(prop => prop.escapedName === 'type'); - - if ($type) { - const type = typeChecker.getTypeOfSymbolAtLocation($type, symbolNode); - return Number(typeChecker.typeToString(type)); - } - - return 0; + return inferComponentType(typeChecker, symbolNode) ?? 0; } function getProps() { - const $props = symbolProperties.find(prop => prop.escapedName === 'props'); + const propsType = inferComponentProps(typeChecker, symbolNode); const vnodeEventRegex = /^onVnode[A-Z]/; let result: PropertyMeta[] = []; - if ($props) { - const type = typeChecker.getTypeOfSymbolAtLocation($props, symbolNode); - const properties = type.getProperties(); + if (propsType) { + const properties = propsType.getProperties(); const eventProps = new Set( meta.events.map(event => `on${event.name.charAt(0).toUpperCase()}${event.name.slice(1)}`), @@ -403,11 +364,10 @@ interface ComponentMeta { } function getEvents() { - const $emit = symbolProperties.find(prop => prop.escapedName === 'emit'); + const emitType = inferComponentEmit(typeChecker, symbolNode); - if ($emit) { - const type = typeChecker.getTypeOfSymbolAtLocation($emit, symbolNode); - const calls = type.getCallSignatures(); + if (emitType) { + const calls = emitType.getCallSignatures(); return calls.map(call => { const { @@ -422,11 +382,10 @@ interface ComponentMeta { } function getSlots() { - const $slots = symbolProperties.find(prop => prop.escapedName === 'slots'); + const slotsType = inferComponentSlots(typeChecker, symbolNode); - if ($slots) { - const type = typeChecker.getTypeOfSymbolAtLocation($slots, symbolNode); - const properties = type.getProperties(); + if (slotsType) { + const properties = slotsType.getProperties(); return properties.map(prop => { const { @@ -441,13 +400,12 @@ interface ComponentMeta { } function getExposed() { - const $exposed = symbolProperties.find(prop => prop.escapedName === 'exposed'); + const exposedType = inferComponentExposed(typeChecker, symbolNode); - if ($exposed) { - const $props = symbolProperties.find(prop => prop.escapedName === 'props'); - const propsProperties = $props ? typeChecker.getTypeOfSymbolAtLocation($props, symbolNode).getProperties() : []; - const type = typeChecker.getTypeOfSymbolAtLocation($exposed, symbolNode); - const properties = type.getProperties().filter(prop => + if (exposedType) { + const propsType = inferComponentProps(typeChecker, symbolNode); + const propsProperties = propsType?.getProperties() ?? []; + const properties = exposedType.getProperties().filter(prop => // only exposed props will have at least one declaration and no valueDeclaration prop.declarations?.length && !prop.valueDeclaration @@ -489,46 +447,6 @@ interface ComponentMeta { } } - function _getExports( - program: ts.Program, - typeChecker: ts.TypeChecker, - componentPath: string, - ) { - const sourceFile = program.getSourceFile(getMetaFileName(componentPath)); - if (!sourceFile) { - throw 'Could not find main source file'; - } - - const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile); - if (!moduleSymbol) { - throw 'Could not find module symbol'; - } - - const exportedSymbols = typeChecker.getExportsOfModule(moduleSymbol); - - let symbolNode: ts.Expression | undefined; - - for (const symbol of exportedSymbols) { - const [declaration] = symbol.getDeclarations() ?? []; - - if (declaration && ts.isExportAssignment(declaration)) { - symbolNode = declaration.expression; - } - } - - if (!symbolNode) { - throw 'Could not find symbol node'; - } - - const exportDefaultType = typeChecker.getTypeAtLocation(symbolNode); - const exports = exportDefaultType.getProperties(); - - return { - symbolNode, - exports, - }; - } - function getScriptRanges(sourceFile: ts.SourceFile) { let scriptRanges = scriptRangesCache.get(sourceFile); if (!scriptRanges) { diff --git a/packages/component-meta/lib/helpers.ts b/packages/component-meta/lib/helpers.ts new file mode 100644 index 0000000000..4b85c51a94 --- /dev/null +++ b/packages/component-meta/lib/helpers.ts @@ -0,0 +1,153 @@ +import type * as ts from 'typescript'; + +export function inferComponentType( + typeChecker: ts.TypeChecker, + symbolNode: ts.Node, +) { + const componentType = typeChecker.getTypeAtLocation(symbolNode); + const constructSignatures = componentType.getConstructSignatures(); + const callSignatures = componentType.getCallSignatures(); + + for (const _sig of constructSignatures) { + return 1; + } + + for (const _sig of callSignatures) { + return 2; + } +} + +export function inferComponentProps( + typeChecker: ts.TypeChecker, + symbolNode: ts.Node, +): ts.Type | undefined { + const componentType = typeChecker.getTypeAtLocation(symbolNode); + const constructSignatures = componentType.getConstructSignatures(); + const callSignatures = componentType.getCallSignatures(); + + for (const sig of constructSignatures) { + const retType = sig.getReturnType(); + const props = findProperty(typeChecker, symbolNode, retType, '$props'); + if (props) { + return props; + } + } + + for (const sig of callSignatures) { + if (sig.parameters.length > 0) { + const props = sig.parameters[0]; + if (props) { + return typeChecker.getTypeOfSymbolAtLocation(props, symbolNode); + } + } + } +} + +export function inferComponentSlots( + typeChecker: ts.TypeChecker, + symbolNode: ts.Node, +): ts.Type | undefined { + const componentType = typeChecker.getTypeAtLocation(symbolNode); + const constructSignatures = componentType.getConstructSignatures(); + const callSignatures = componentType.getCallSignatures(); + + for (const sig of constructSignatures) { + const retType = sig.getReturnType(); + const slots = findProperty(typeChecker, symbolNode, retType, '$slots'); + if (slots) { + return slots; + } + } + + for (const sig of callSignatures) { + if (sig.parameters.length > 1) { + const ctxParam = sig.parameters[1]; + if (ctxParam) { + const ctxType = typeChecker.getTypeOfSymbolAtLocation(ctxParam, symbolNode); + const slots = findProperty(typeChecker, symbolNode, ctxType, 'slots'); + if (slots) { + return slots; + } + } + } + } +} + +export function inferComponentEmit( + typeChecker: ts.TypeChecker, + symbolNode: ts.Node, +): ts.Type | undefined { + const componentType = typeChecker.getTypeAtLocation(symbolNode); + const constructSignatures = componentType.getConstructSignatures(); + const callSignatures = componentType.getCallSignatures(); + + for (const sig of constructSignatures) { + const retType = sig.getReturnType(); + const emit = findProperty(typeChecker, symbolNode, retType, '$emit'); + if (emit) { + return emit; + } + } + + for (const sig of callSignatures) { + if (sig.parameters.length > 1) { + const ctxParam = sig.parameters[1]; + if (ctxParam) { + const ctxType = typeChecker.getTypeOfSymbolAtLocation(ctxParam, symbolNode); + const emitType = findProperty(typeChecker, symbolNode, ctxType, 'emit'); + if (emitType) { + return emitType; + } + } + } + } +} + +export function inferComponentExposed( + typeChecker: ts.TypeChecker, + symbolNode: ts.Node, +): ts.Type | undefined { + const componentType = typeChecker.getTypeAtLocation(symbolNode); + const constructSignatures = componentType.getConstructSignatures(); + const callSignatures = componentType.getCallSignatures(); + + for (const sig of constructSignatures) { + return sig.getReturnType(); + } + + for (const sig of callSignatures) { + if (sig.parameters.length > 2) { + const exposeParam = sig.parameters[2]; + if (exposeParam) { + const exposeType = typeChecker.getTypeOfSymbolAtLocation(exposeParam, symbolNode); + const callSignatures = exposeType.getCallSignatures(); + for (const callSig of callSignatures) { + const params = callSig.getParameters(); + if (params.length > 0) { + return typeChecker.getTypeOfSymbolAtLocation(params[0]!, symbolNode); + } + } + } + } + } +} + +function findProperty( + typeChecker: ts.TypeChecker, + symbolNode: ts.Node, + type: ts.Type, + propertyName: string, +): ts.Type | undefined { + const emit = type.getProperty(propertyName); + if (emit) { + return typeChecker.getTypeOfSymbolAtLocation(emit, symbolNode); + } + if (type.isUnionOrIntersection()) { + for (const sub of type.types) { + const found = findProperty(typeChecker, symbolNode, sub, propertyName); + if (found) { + return found; + } + } + } +} diff --git a/packages/component-meta/package.json b/packages/component-meta/package.json index 48a4946fa1..cf1a9ce2a9 100644 --- a/packages/component-meta/package.json +++ b/packages/component-meta/package.json @@ -15,8 +15,7 @@ "dependencies": { "@volar/typescript": "2.4.27", "@vue/language-core": "workspace:*", - "path-browserify": "^1.0.1", - "vue-component-type-helpers": "workspace:*" + "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" diff --git a/packages/language-core/lib/parsers/scriptRanges.ts b/packages/language-core/lib/parsers/scriptRanges.ts index 2d04882b62..6bbd79211f 100644 --- a/packages/language-core/lib/parsers/scriptRanges.ts +++ b/packages/language-core/lib/parsers/scriptRanges.ts @@ -14,7 +14,7 @@ export function parseScriptRanges( const _exports: Record< 'default' | string, TextRange & { - expression: TextRange; + expression: TextRange; isObjectLiteral: boolean; options?: { isObjectLiteral: boolean; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9453ea4e74..89768bcba6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,9 +89,6 @@ importers: typescript: specifier: '*' version: 5.9.3 - vue-component-type-helpers: - specifier: workspace:* - version: link:../component-type-helpers devDependencies: '@types/node': specifier: ^22.10.4 From 3ab3a94e98de673f36a3bbf5bbe3ce09a9febfc9 Mon Sep 17 00:00:00 2001 From: Johnson Chu Date: Mon, 15 Dec 2025 20:46:51 +0800 Subject: [PATCH 2/5] Update base.ts --- packages/component-meta/lib/base.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/component-meta/lib/base.ts b/packages/component-meta/lib/base.ts index 809ed9bf6d..79d36b0f31 100644 --- a/packages/component-meta/lib/base.ts +++ b/packages/component-meta/lib/base.ts @@ -245,35 +245,35 @@ function baseCreate( const symbolNode = component.expression.node; const typeChecker = program.getTypeChecker(); - let _type: ReturnType | undefined; - let _props: ReturnType | undefined; - let _events: ReturnType | undefined; - let _slots: ReturnType | undefined; - let _exposed: ReturnType | undefined; - let _name: string | undefined; - let _description: string | undefined; + let name: string | undefined; + let description: string | undefined; + let type: ReturnType | undefined; + let props: ReturnType | undefined; + let events: ReturnType | undefined; + let slots: ReturnType | undefined; + let exposed: ReturnType | undefined; const meta = { get name() { - return _name ?? (_name = getName()); + return name ?? (name = getName()); }, get description() { - return _description ?? (_description = getDescription()); + return description ?? (description = getDescription()); }, get type() { - return _type ?? (_type = getType()); + return type ?? (type = getType()); }, get props() { - return _props ?? (_props = getProps()); + return props ?? (props = getProps()); }, get events() { - return _events ?? (_events = getEvents()); + return events ?? (events = getEvents()); }, get slots() { - return _slots ?? (_slots = getSlots()); + return slots ?? (slots = getSlots()); }, get exposed() { - return _exposed ?? (_exposed = getExposed()); + return exposed ?? (exposed = getExposed()); }, }; From 583f8935fd548c32ea4f2dc69ef71c2b54db7bf1 Mon Sep 17 00:00:00 2001 From: Johnson Chu Date: Tue, 16 Dec 2025 07:49:20 +0800 Subject: [PATCH 3/5] wip --- packages/component-meta/lib/helpers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/component-meta/lib/helpers.ts b/packages/component-meta/lib/helpers.ts index 4b85c51a94..5b2fe468e1 100644 --- a/packages/component-meta/lib/helpers.ts +++ b/packages/component-meta/lib/helpers.ts @@ -138,9 +138,9 @@ function findProperty( type: ts.Type, propertyName: string, ): ts.Type | undefined { - const emit = type.getProperty(propertyName); - if (emit) { - return typeChecker.getTypeOfSymbolAtLocation(emit, symbolNode); + const prop = type.getProperty(propertyName); + if (prop) { + return typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode); } if (type.isUnionOrIntersection()) { for (const sub of type.types) { From 03f0ece93a7322641345775ea3cbba56ffb19627 Mon Sep 17 00:00:00 2001 From: Johnson Chu Date: Tue, 16 Dec 2025 10:14:29 +0800 Subject: [PATCH 4/5] improve public props check --- packages/component-meta/lib/base.ts | 73 +++++++++++++++----------- packages/component-meta/lib/helpers.ts | 12 ++--- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/packages/component-meta/lib/base.ts b/packages/component-meta/lib/base.ts index 79d36b0f31..79d898ccc7 100644 --- a/packages/component-meta/lib/base.ts +++ b/packages/component-meta/lib/base.ts @@ -54,7 +54,6 @@ export function createCheckerByJsonConfigBase( }, checkerOptions, rootDir, - path.join(rootDir, 'jsconfig.json.global.vue'), ); } @@ -86,7 +85,6 @@ export function createCheckerBase( }, checkerOptions, path.dirname(tsconfig), - tsconfig + '.global.vue', ); } @@ -98,7 +96,6 @@ function baseCreate( ], checkerOptions: MetaCheckerOptions, rootPath: string, - globalComponentName: string, ) { let [{ vueOptions, options, projectReferences }, fileNames] = getConfigAndFiles(); /** @@ -112,13 +109,9 @@ function baseCreate( getCurrentDirectory: () => rootPath, getProjectVersion: () => projectVersion.toString(), getCompilationSettings: () => options, - getScriptFileNames: () => [ - ...[...fileNamesSet], - globalComponentName, - ], + getScriptFileNames: () => [...fileNamesSet], getProjectReferences: () => projectReferences, }; - const globalComponentSnapshot = ts.ScriptSnapshot.fromString(''); const scriptSnapshots = new Map(); const vueLanguagePlugin = core.createVueLanguagePlugin( ts, @@ -139,21 +132,16 @@ function baseCreate( fileName => { let snapshot = scriptSnapshots.get(fileName); - if (fileName === globalComponentName) { - snapshot = globalComponentSnapshot; - } - else { - if (!scriptSnapshots.has(fileName)) { - const fileText = ts.sys.readFile(fileName); - if (fileText !== undefined) { - scriptSnapshots.set(fileName, ts.ScriptSnapshot.fromString(fileText)); - } - else { - scriptSnapshots.set(fileName, undefined); - } + if (!scriptSnapshots.has(fileName)) { + const fileText = ts.sys.readFile(fileName); + if (fileText !== undefined) { + scriptSnapshots.set(fileName, ts.ScriptSnapshot.fromString(fileText)); + } + else { + scriptSnapshots.set(fileName, undefined); } - snapshot = scriptSnapshots.get(fileName); } + snapshot = scriptSnapshots.get(fileName); if (snapshot) { language.scripts.set(fileName, snapshot); @@ -183,8 +171,6 @@ function baseCreate( }; } - let globalPropNames: string[] | undefined; - return { getExportNames, getComponentMeta, @@ -306,14 +292,6 @@ function baseCreate( .filter(prop => !vnodeEventRegex.test(prop.name) && !eventProps.has(prop.name)); } - // fill global - if (componentPath !== globalComponentName) { - globalPropNames ??= getComponentMeta(globalComponentName).props.map(prop => prop.name); - for (const prop of result) { - prop.global = globalPropNames.includes(prop.name); - } - } - // fill defaults const sourceScript = language.scripts.get(componentPath); const sourceFile = program.getSourceFile(componentPath); @@ -523,10 +501,20 @@ function createSchemaResolvers( const subtype = typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode); let schema: PropertyMetaSchema | undefined; let declarations: Declaration[] | undefined; + let global = false; + + for (const decl of prop.declarations ?? []) { + if ( + decl.getSourceFile() !== symbolNode.getSourceFile() + && isPublicProp(decl) + ) { + global = true; + } + } return { name: prop.getEscapedName().toString(), - global: false, + global, description: ts.displayPartsToString(prop.getDocumentationComment(typeChecker)), tags: getJsDocTags(prop), required: !(prop.flags & ts.SymbolFlags.Optional), @@ -543,6 +531,27 @@ function createSchemaResolvers( }, }; } + + function isPublicProp(declaration: ts.Declaration): boolean { + const publicInterfaces = new Set([ + 'PublicProps', + 'VNodeProps', + 'AllowedComponentProps', + 'ComponentCustomProps', + ]); + let parent = declaration.parent; + while (parent) { + if (ts.isInterfaceDeclaration(parent) || ts.isTypeAliasDeclaration(parent)) { + if (publicInterfaces.has(parent.name.text)) { + return true; + } + return false; + } + parent = parent.parent; + } + return false; + } + function resolveSlotProperties(prop: ts.Symbol): SlotMeta { const propType = typeChecker.getNonNullableType(typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode)); const signatures = propType.getCallSignatures(); diff --git a/packages/component-meta/lib/helpers.ts b/packages/component-meta/lib/helpers.ts index 5b2fe468e1..750691bda1 100644 --- a/packages/component-meta/lib/helpers.ts +++ b/packages/component-meta/lib/helpers.ts @@ -134,17 +134,17 @@ export function inferComponentExposed( function findProperty( typeChecker: ts.TypeChecker, - symbolNode: ts.Node, + location: ts.Node, type: ts.Type, - propertyName: string, + property: string, ): ts.Type | undefined { - const prop = type.getProperty(propertyName); - if (prop) { - return typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode); + const symbol = type.getProperty(property); + if (symbol) { + return typeChecker.getTypeOfSymbolAtLocation(symbol, location); } if (type.isUnionOrIntersection()) { for (const sub of type.types) { - const found = findProperty(typeChecker, symbolNode, sub, propertyName); + const found = findProperty(typeChecker, location, sub, property); if (found) { return found; } From 35c89c5b1b237dc4925aa75cb2b85b405032b3bf Mon Sep 17 00:00:00 2001 From: Johnson Chu Date: Tue, 16 Dec 2025 10:15:00 +0800 Subject: [PATCH 5/5] Update base.ts --- packages/component-meta/lib/base.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/component-meta/lib/base.ts b/packages/component-meta/lib/base.ts index 79d898ccc7..ca7a50d536 100644 --- a/packages/component-meta/lib/base.ts +++ b/packages/component-meta/lib/base.ts @@ -24,6 +24,12 @@ import type { export * from './types'; const windowsPathReg = /\\/g; +const publicPropsInterfaces = new Set([ + 'PublicProps', + 'VNodeProps', + 'AllowedComponentProps', + 'ComponentCustomProps', +]); export function createCheckerByJsonConfigBase( ts: typeof import('typescript'), @@ -533,16 +539,10 @@ function createSchemaResolvers( } function isPublicProp(declaration: ts.Declaration): boolean { - const publicInterfaces = new Set([ - 'PublicProps', - 'VNodeProps', - 'AllowedComponentProps', - 'ComponentCustomProps', - ]); let parent = declaration.parent; while (parent) { if (ts.isInterfaceDeclaration(parent) || ts.isTypeAliasDeclaration(parent)) { - if (publicInterfaces.has(parent.name.text)) { + if (publicPropsInterfaces.has(parent.name.text)) { return true; } return false;