Skip to content

Commit 4fa674b

Browse files
committed
fix(complex-types): disallow printing reserved properties
1 parent 486af96 commit 4fa674b

File tree

5 files changed

+58
-17
lines changed

5 files changed

+58
-17
lines changed

packages/complex-types/src/core/printer.ts

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@ export class Printer {
1616
private printUnionOrIntersection(
1717
type: ts.UnionOrIntersectionType,
1818
separator: string,
19+
isPropertyBlacklisted: (prop: string) => boolean,
1920
inner: boolean,
2021
): string {
2122
return [
2223
...new Set(
23-
type.types.map((t) => this.printType(t, inner)).filter(Boolean),
24+
type.types
25+
.map((t) => this.printType(t, isPropertyBlacklisted, inner))
26+
.filter(Boolean),
2427
),
2528
].join(separator);
2629
}
@@ -29,13 +32,17 @@ export class Printer {
2932
return !!(symbol.flags & ts.SymbolFlags.Optional);
3033
}
3134

32-
private printConditionType(type: ts.ConditionalType, inner: boolean): string {
35+
private printConditionType(
36+
type: ts.ConditionalType,
37+
isPropertyBlacklisted: (prop: string) => boolean,
38+
inner: boolean,
39+
): string {
3340
const decl = type.root.node;
3441
const { trueType, falseType } = decl;
3542
const trueTypeNode = this.checker.getTypeAtLocation(trueType);
3643
const falseTypeNode = this.checker.getTypeAtLocation(falseType);
3744

38-
return `${this.printType(trueTypeNode, inner)} | ${this.printType(falseTypeNode, inner)}`;
45+
return `${this.printType(trueTypeNode, isPropertyBlacklisted, inner)} | ${this.printType(falseTypeNode, isPropertyBlacklisted, inner)}`;
3946
}
4047

4148
private printPrimitiveType(type: ts.Type): string {
@@ -58,11 +65,25 @@ export class Printer {
5865
return "";
5966
}
6067

61-
private printType(type: ts.Type, inner = false): string {
68+
private printType(
69+
type: ts.Type,
70+
isPropertyBlacklisted: (prop: string) => boolean,
71+
inner = false,
72+
): string {
6273
if (type.isUnion()) {
63-
return this.printUnionOrIntersection(type, " | ", inner);
74+
return this.printUnionOrIntersection(
75+
type,
76+
" | ",
77+
isPropertyBlacklisted,
78+
inner,
79+
);
6480
} else if (type.isIntersection()) {
65-
return this.printUnionOrIntersection(type, " & ", inner);
81+
return this.printUnionOrIntersection(
82+
type,
83+
" & ",
84+
isPropertyBlacklisted,
85+
inner,
86+
);
6687
}
6788
if (this.checker.isArrayType(type)) {
6889
return "Array";
@@ -86,8 +107,13 @@ export class Printer {
86107
> = {};
87108
for (const prop of properties) {
88109
const propType = this.checker.getTypeOfSymbol(prop);
89-
props[prop.getName()] = {
90-
value: this.printType(propType, true),
110+
const name = prop.getName();
111+
if (isPropertyBlacklisted(name)) {
112+
continue;
113+
}
114+
115+
props[name] = {
116+
value: this.printType(propType, isPropertyBlacklisted, true),
91117
isOptional: this.isSymbolOptional(prop),
92118
};
93119
}
@@ -113,7 +139,11 @@ export class Printer {
113139
} else if (type.flags & ts.TypeFlags.Undefined) {
114140
return "";
115141
} else if (type.flags & ts.TypeFlags.Conditional) {
116-
return this.printConditionType(type as ts.ConditionalType, inner);
142+
return this.printConditionType(
143+
type as ts.ConditionalType,
144+
isPropertyBlacklisted,
145+
inner,
146+
);
117147
} else if (type.isTypeParameter()) {
118148
const symbol = type.getSymbol();
119149
const decl = symbol?.declarations?.[0];
@@ -126,16 +156,19 @@ export class Printer {
126156
}
127157
const refType = this.checker.getTypeAtLocation(ref);
128158

129-
return this.printType(refType, inner);
159+
return this.printType(refType, isPropertyBlacklisted, inner);
130160
}
131161

132162
return this.typeToString(type);
133163
}
134164

135-
public printPropsTypeArg(node: ts.Node): string {
165+
public printPropsTypeArg(
166+
node: ts.Node,
167+
isPropertyBlacklisted: (prop: string) => boolean,
168+
): string {
136169
const type = this.checker.getTypeAtLocation(node);
137170

138-
return this.printType(type);
171+
return this.printType(type, isPropertyBlacklisted);
139172
}
140173

141174
private printEventsByCallSignatures(

packages/complex-types/src/core/transformers/defineProps.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { isReservedProp } from "@vue/shared";
12
import { getLanguage } from "@vue.ts/language";
23
import { normalizePath } from "@vue.ts/shared";
34

@@ -23,7 +24,10 @@ export const transformDefineProps: Transformer = (printer, s, id) => {
2324
return;
2425
}
2526

26-
const printedType = printer.printPropsTypeArg(virtualFileDefinePropsTypeNode);
27+
const printedType = printer.printPropsTypeArg(
28+
virtualFileDefinePropsTypeNode,
29+
isReservedProp,
30+
);
2731
const offset = scriptSetupBlock.startTagEnd;
2832

2933
s.overwrite(

packages/complex-types/test/__fixtures__/defineProps/basic.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ defineProps<
3030
'quotes"': string;
3131
enum: SomeEnum;
3232
anyQuestion?: any;
33+
// Reserved Property
34+
onVnodeUpdated: 1;
3335
} & SomeInterface & {
3436
[MappedString in "1-1" | "1-2"]: `${MappedString}MappedType`;
3537
} & {

packages/complex-types/test/__snapshots__/fixtures-compiled.test.ts.snap

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
153153
type: [String, Number],
154154
required: true
155155
},
156+
anyQuestion: { required: false },
156157
emptyInterface: {
157158
type: Object,
158159
required: true
@@ -263,7 +264,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
263264
type: String,
264265
required: false
265266
},
266-
class: { required: true },
267+
class: { required: false },
267268
style: {
268269
type: [String, Boolean],
269270
skipCheck: true,
@@ -341,7 +342,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
341342
type: String,
342343
required: false
343344
},
344-
inlist: { required: true },
345+
inlist: { required: false },
345346
prefix: {
346347
type: String,
347348
required: false

packages/complex-types/test/__snapshots__/fixtures.test.ts.snap

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ defineProps<
6363
"symbol": symbol,
6464
"quotes\\"": string,
6565
"enum": string | number,
66+
"anyQuestion"?: any,
6667
} & {
6768
"emptyInterface": object,
6869
"conditionalNumber": number,
@@ -99,7 +100,7 @@ defineProps<{
99100
"type"?: string,
100101
"value"?: string | number | Array,
101102
"innerHTML"?: string,
102-
"class": any,
103+
"class"?: any,
103104
"style"?: null | string | boolean | object | Array,
104105
"accesskey"?: string,
105106
"contenteditable"?: boolean | string,
@@ -119,7 +120,7 @@ defineProps<{
119120
"role"?: string,
120121
"about"?: string,
121122
"datatype"?: string,
122-
"inlist": any,
123+
"inlist"?: any,
123124
"prefix"?: string,
124125
"property"?: string,
125126
"resource"?: string,

0 commit comments

Comments
 (0)