@mirascript/typed 0.1.64 → 0.1.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/type.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/type.peggy"],"names":["$top_level_initializer","Start","UnionType","PostfixType","PrimaryType","TypeParamList","TypeArgList","FunctionType","NamedFunction","FunctionBody","FunctionParamList","FunctionParam","RecordType","FieldList","Field","FieldName","HexDigit","EscapeSequence","String","DoubleQuotePart","SingleQuotePart","BacktickPart","DoubleQuoteChar","SingleQuoteChar","BacktickChar","Identifier","_","$initializer"],"mappings":"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","file":"type.js"}
1
+ {"version":3,"sources":["../src/type.peggy"],"names":["$top_level_initializer","Start","UnionType","IntersectionType","PostfixType","PrimaryType","ReflectionType","TupleType","TupleElementList","TupleElement","TypeParamList","TypeArgList","FunctionType","NamedFunction","FunctionBody","FunctionParamList","FunctionParam","RecordType","FieldList","Field","FieldName","HexDigit","EscapeSequence","String","DoubleQuotePart","SingleQuotePart","BacktickPart","DoubleQuoteChar","SingleQuoteChar","BacktickChar","Identifier","_","$initializer"],"mappings":";;;;;AAAEA;AACFA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBA2DoD;AACpD;AACI,G;sBAG2C;AAC/C;AACI,G;iCAOmC;AACvC;AACA;AACA;AACA;AACI,G;kCAUuD;AAC3D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACI,G;wBACY;AAChB;AACA;AACI,G;yBAUsC;AAC1C;AACI,G;6BAOwC;AAC5C;AACI,G;iCAM0B;AAC9B;AACI,G;yBAkB0B,gBAAc,G;+BAGI;AAChD;AACA;AACA;AACI,G;6CAG0G;AAC9G;AACA;AACA;AACA;AACI,G;4BAGkD;AACtD;AACA;AACA;AACA;AACI,G;qCAGiD;AACrD;AACA;AACA;AACA;AACA;AACI,G;6BACoC;AACxC;AACI,G;4BAO+B,gCAA8B,G;kCAMnB;AAC9C;AACA;AACA;AACA;AACA;AACI,G;0BACW,oBAAkB,G;0BAIhB;AACjB;AACA;AACI,G;0BAU6B;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACE,G;yBAAoC;AACtC;AACA;AACA;AACA;AACE,G;yBAAiC;AACnC;AACA;AACA;AACA;AACA;AACA;AACE,G;2BAGkC,yBAAuB,G;2BACvB,yBAAuB,G;2BAC1B,yBAAuB,G;2BAI5B,mCAAiC,G;2BAIjC,mCAAiC,G;2BAIpC,mCAAiC,G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WApO1DC,cAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAWLC,kBAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAKTC,yBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAShBC,oBAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAYXC,oBAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAyCXC,uBAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WASdC,kBAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAKTC,yBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAGhBC,qBAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;WAUZC,sBAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAGbC,oBAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAOXC,qBAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAGZC,sBAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAObC,qBAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAQZC,0BAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAQjBC,sBAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAgBbC,mBAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAGVC,kBAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAGTC,cAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAULC,kBAAS;;;;;;;;;;;;;;;;;WAWTC,iBAAQ;;;;;;;;;;;;;;;;;;;;WAGRC,uBAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA0BdC,eAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAKNC,wBAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAIfC,wBAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAIfC,qBAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAIZC,wBAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAIfC,wBAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAIfC,qBAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAIZC,mBAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAGVC,UAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;AAjSAC;AACDA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA","file":"type.js"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mirascript/typed",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "author": "CloudPSS",
5
5
  "license": "MIT",
6
6
  "description": "Parse MiraScript type definitions and generate TypeScript types / JSON schemas.",
@@ -23,15 +23,16 @@
23
23
  "./package.json": "./package.json"
24
24
  },
25
25
  "devDependencies": {
26
- "@types/node": "^26.0.1",
26
+ "@types/node": "^26.1.1",
27
27
  "ava": "^8.0.1",
28
28
  "c8": "^11.0.0",
29
- "js-yaml": "^5.2.0",
30
- "peggy": "^5.1.0"
29
+ "js-yaml": "^5.2.1",
30
+ "peggy": "^5.1.0",
31
+ "@mirascript/mirascript": "~0.1.65"
31
32
  },
32
33
  "dependencies": {
33
- "@types/json-schema": "^7.0.15",
34
- "@mirascript/constants": "~0.1.64"
34
+ "json-schema-typed": "^8.0.2",
35
+ "@mirascript/constants": "~0.1.65"
35
36
  },
36
37
  "scripts": {
37
38
  "build": "peggy src/type.peggy --multi-output ./dist --dts --format es --source-map && tsc",
package/src/index.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  export * from './parser.js';
2
+ export * from './simplifier.js';
2
3
  export * from './json.js';
4
+ export * from './stringify.js';
package/src/json.ts CHANGED
@@ -1,9 +1,10 @@
1
- import type { JSONSchema7 } from 'json-schema';
1
+ import type { JSONSchema } from 'json-schema-typed';
2
2
  import { REG_NUMBER } from '@mirascript/constants';
3
+ import { simplify } from './simplifier.js';
3
4
  import type { KnownType, LiteralType, NamedType, TemplateType, Type } from './parser.js';
4
5
 
5
6
  /** Converts a KnownType or NamedType into JSON Schema */
6
- function string(type: KnownType | NamedType): JSONSchema7 {
7
+ function string(type: KnownType | NamedType): JSONSchema {
7
8
  switch (type) {
8
9
  case 'string':
9
10
  return { type: 'string' };
@@ -14,19 +15,19 @@ function string(type: KnownType | NamedType): JSONSchema7 {
14
15
  case 'nil':
15
16
  return { type: 'null' };
16
17
  case 'array':
17
- return { type: 'array' };
18
+ return { type: 'array', items: true };
18
19
  case 'record':
19
20
  return { type: 'object' };
20
21
  case 'extern':
21
- return {};
22
+ return true;
22
23
  case 'any':
23
- return {};
24
+ return true;
24
25
  case 'unknown':
25
- return {};
26
+ return true;
26
27
  case 'never':
27
- return {};
28
+ return false;
28
29
  default:
29
- return {};
30
+ return true;
30
31
  }
31
32
  }
32
33
 
@@ -83,6 +84,9 @@ function templatePartPattern(part: Type, grouping: boolean): string {
83
84
  result = `(${result})?`;
84
85
  }
85
86
  }
87
+ } else if (part.kind === 'intersection') {
88
+ // Regex intersection is not representable in general; keep behavior conservative.
89
+ result = RE_ANY;
86
90
  } else {
87
91
  result = RE_ANY;
88
92
  }
@@ -104,27 +108,21 @@ function templatePattern(type: TemplateType): string {
104
108
  }
105
109
 
106
110
  /** Converts a LiteralType into JSON Schema */
107
- function literal(type: LiteralType): JSONSchema7 {
108
- if (typeof type.value === 'boolean') {
109
- return { type: 'boolean', const: type.value };
110
- }
111
- return { type: 'string', const: type.value };
111
+ function literal(type: LiteralType): JSONSchema {
112
+ return { const: type.value };
112
113
  }
113
114
 
114
115
  /** Converts a union of LiteralTypes into a single JSON Schema enum */
115
- function literalEnum(types: LiteralType[]): JSONSchema7 {
116
- const values = types.map((t) => t.value);
117
- const valueTypes = new Set(values.map((v) => (typeof v === 'boolean' ? 'boolean' : 'string')));
118
- const schema: JSONSchema7 = { enum: values };
119
- if (valueTypes.size === 1) {
120
- schema.type = valueTypes.values().next().value!;
121
- }
116
+ function literalEnum(types: LiteralType[]): JSONSchema {
117
+ const schema: JSONSchema = {
118
+ enum: types.map((t) => t.value),
119
+ };
122
120
  return schema;
123
121
  }
124
122
 
125
123
  /** Type guard for LiteralType */
126
124
  function isLiteralType(type: Type): type is LiteralType {
127
- return typeof type === 'object' && type.kind === 'literal';
125
+ return typeof type == 'object' && type.kind === 'literal';
128
126
  }
129
127
 
130
128
  /** Options for toJSONSchema */
@@ -134,24 +132,25 @@ export interface ToJSONSchemaOptions {
134
132
  }
135
133
 
136
134
  /** Converts a Type object into JSON Schema */
137
- export function toJSONSchema(type: Type, options?: ToJSONSchemaOptions): JSONSchema7 {
135
+ export function toJSONSchema(type: Type, options?: ToJSONSchemaOptions): JSONSchema {
138
136
  const loose = options?.loose ?? false;
139
- if (typeof type === 'symbol') {
137
+ const simplified = simplify(type);
138
+ if (typeof simplified == 'symbol') {
140
139
  return {};
141
140
  }
142
- if (typeof type === 'string') {
143
- return string(type);
141
+ if (typeof simplified == 'string') {
142
+ return string(simplified);
144
143
  }
145
- if (type.kind === 'array') {
144
+ if (simplified.kind === 'array') {
146
145
  return {
147
146
  type: 'array',
148
- items: toJSONSchema(type.element, options),
147
+ items: toJSONSchema(simplified.element, options),
149
148
  };
150
149
  }
151
- if (type.kind === 'union') {
152
- const anyOf = [];
153
- const literals = [];
154
- for (const t of type.types) {
150
+ if (simplified.kind === 'union') {
151
+ const anyOf: JSONSchema[] = [];
152
+ const literals: LiteralType[] = [];
153
+ for (const t of simplified.types) {
155
154
  if (isLiteralType(t)) {
156
155
  literals.push(t);
157
156
  } else {
@@ -166,17 +165,24 @@ export function toJSONSchema(type: Type, options?: ToJSONSchemaOptions): JSONSch
166
165
  }
167
166
  return { anyOf };
168
167
  }
169
- if (type.kind === 'record') {
170
- if ('fields' in type) {
171
- const properties: Record<string, JSONSchema7> = {};
168
+ if (simplified.kind === 'intersection') {
169
+ const allOf = simplified.types.map((t) => toJSONSchema(t, options));
170
+ if (allOf.length === 1) {
171
+ return allOf[0]!;
172
+ }
173
+ return { allOf };
174
+ }
175
+ if (simplified.kind === 'record') {
176
+ if ('fields' in simplified) {
177
+ const properties: Record<string, JSONSchema> = {};
172
178
  const required: string[] = [];
173
- for (const field of type.fields) {
179
+ for (const field of simplified.fields) {
174
180
  properties[field.name] = toJSONSchema(field.type, options);
175
181
  if (!field.optional && !loose) {
176
182
  required.push(field.name);
177
183
  }
178
184
  }
179
- const schema: JSONSchema7 = {
185
+ const schema: JSONSchema = {
180
186
  type: 'object',
181
187
  properties,
182
188
  additionalProperties: loose,
@@ -187,54 +193,102 @@ export function toJSONSchema(type: Type, options?: ToJSONSchemaOptions): JSONSch
187
193
  return schema;
188
194
  }
189
195
 
190
- const valueSchema = toJSONSchema(type.value, options);
191
- if (type.key == null) {
196
+ const valueSchema = toJSONSchema(simplified.value, options);
197
+ if (simplified.key == null) {
192
198
  return {
193
199
  type: 'object',
194
200
  additionalProperties: valueSchema,
195
201
  };
196
202
  }
197
- if (typeof type.key == 'object') {
198
- if (isLiteralType(type.key)) {
199
- const schema: JSONSchema7 = {
203
+ if (typeof simplified.key == 'object') {
204
+ if (isLiteralType(simplified.key)) {
205
+ const schema: JSONSchema = {
200
206
  type: 'object',
201
- properties: { [String(type.key.value)]: valueSchema },
207
+ properties: { [String(simplified.key.value)]: valueSchema },
202
208
  additionalProperties: loose,
203
209
  };
204
210
  return schema;
205
- } else if (type.key.kind === 'union' && type.key.types.every(isLiteralType)) {
206
- const schema: JSONSchema7 = {
211
+ } else if (simplified.key.kind === 'union' && simplified.key.types.every(isLiteralType)) {
212
+ const schema: JSONSchema = {
207
213
  type: 'object',
208
- properties: Object.fromEntries(type.key.types.map((t) => [String(t.value), valueSchema])),
214
+ properties: Object.fromEntries(simplified.key.types.map((t) => [String(t.value), valueSchema])),
209
215
  additionalProperties: loose,
210
216
  };
211
217
  return schema;
212
218
  }
213
219
  }
214
- const pattern = templatePartPattern(type.key, false);
220
+ const pattern = templatePartPattern(simplified.key, false);
215
221
  if (pattern === RE_ANY) {
216
222
  return {
217
223
  type: 'object',
218
224
  additionalProperties: valueSchema,
219
225
  };
220
226
  }
221
- const schema: JSONSchema7 = {
227
+ const schema: JSONSchema = {
222
228
  type: 'object',
223
229
  patternProperties: { [`^${pattern}$`]: valueSchema },
224
230
  additionalProperties: loose,
225
231
  };
226
232
  return schema;
227
233
  }
228
- if (type.kind === 'literal') {
229
- return literal(type);
234
+ if (simplified.kind === 'literal') {
235
+ return literal(simplified);
230
236
  }
231
- if (type.kind === 'function') {
232
- return {};
237
+ if (simplified.kind === 'function') {
238
+ return false;
239
+ }
240
+ if (simplified.kind === 'template') {
241
+ return { type: 'string', pattern: templatePattern(simplified) };
242
+ }
243
+ if (simplified.kind === 'tuple') {
244
+ // Collect element schemas, unwrapping array from rest elements (..T[] → T).
245
+ // Non-array rest (e.g. ..string) is treated as any ({}).
246
+ const elementSchemas = simplified.elements.map((e) => {
247
+ const t = e.type;
248
+ if (!e.spread) return toJSONSchema(t, options);
249
+ if (typeof t == 'object' && t.kind === 'array') {
250
+ return toJSONSchema(t.element, options);
251
+ }
252
+ return true;
253
+ });
254
+
255
+ const prefixItems = [];
256
+ let i = 0;
257
+ for (; i < elementSchemas.length; i++) {
258
+ const el = simplified.elements[i]!;
259
+ if (el.spread) break;
260
+ prefixItems.push(elementSchemas[i]!);
261
+ }
262
+
263
+ const items = [];
264
+ let hasAny = false;
265
+ for (; i < elementSchemas.length; i++) {
266
+ const schema = elementSchemas[i]!;
267
+ items.push(schema);
268
+ if (schema === true) {
269
+ hasAny = true;
270
+ }
271
+ }
272
+
273
+ const schema: JSONSchema = { type: 'array' };
274
+ if (prefixItems.length > 0) {
275
+ schema.prefixItems = prefixItems;
276
+ }
277
+ if (hasAny) {
278
+ schema.items = true;
279
+ } else if (items.length > 1) {
280
+ schema.items = { anyOf: items };
281
+ } else if (items.length === 1) {
282
+ schema.items = items[0]!;
283
+ } else {
284
+ schema.items = loose;
285
+ }
286
+ return schema;
233
287
  }
234
- if (type.kind === 'template') {
235
- return { type: 'string', pattern: templatePattern(type) };
288
+ if (simplified.kind === 'reflection') {
289
+ return true;
236
290
  }
237
291
  /* c8 ignore next 3 */
238
- (type) satisfies never;
239
- return {};
292
+ simplified satisfies never;
293
+ return true;
240
294
  }
package/src/parser.ts CHANGED
@@ -9,8 +9,11 @@ export type Type =
9
9
  | TemplateType
10
10
  | ArrayType
11
11
  | UnionType
12
+ | IntersectionType
12
13
  | RecordType
13
- | FunctionType;
14
+ | FunctionType
15
+ | TupleType
16
+ | ReflectionType;
14
17
 
15
18
  /** Generic type parameter reference in MiraScript */
16
19
  export type GenericType = symbol;
@@ -46,6 +49,14 @@ export interface UnionType {
46
49
  types: Type[];
47
50
  }
48
51
 
52
+ /** Intersection type in MiraScript */
53
+ export interface IntersectionType {
54
+ /** Tag */
55
+ kind: 'intersection';
56
+ /** Types in the intersection */
57
+ types: Type[];
58
+ }
59
+
49
60
  /** Array type in MiraScript */
50
61
  export interface ArrayType {
51
62
  /** Tag */
@@ -105,6 +116,30 @@ export interface FunctionParameter {
105
116
  spread?: boolean;
106
117
  }
107
118
 
119
+ /** Tuple type in MiraScript */
120
+ export interface TupleType {
121
+ /** Tag */
122
+ kind: 'tuple';
123
+ /** Elements in the tuple */
124
+ elements: TupleElement[];
125
+ }
126
+
127
+ /** Tuple element in MiraScript */
128
+ export interface TupleElement {
129
+ /** Element type */
130
+ type: Type;
131
+ /** Whether the element is a rest element */
132
+ spread?: boolean;
133
+ }
134
+
135
+ /** Reflection type in MiraScript */
136
+ export interface ReflectionType {
137
+ /** Tag */
138
+ kind: 'reflection';
139
+ /** The name of the variable being reflected */
140
+ name: string;
141
+ }
142
+
108
143
  /**
109
144
  * Replaces generic type parameter names in the AST with unique symbols,
110
145
  * scoped per function declaration.
@@ -136,6 +171,10 @@ function resolveGenerics(type: Type, scope = new Map<string, GenericType>()): Ty
136
171
  type.types = type.types.map((t) => resolveGenerics(t, scope));
137
172
  return type;
138
173
  }
174
+ if (type.kind === 'intersection') {
175
+ type.types = type.types.map((t) => resolveGenerics(t, scope));
176
+ return type;
177
+ }
139
178
  if (type.kind === 'record') {
140
179
  if ('fields' in type) {
141
180
  for (const field of type.fields) {
@@ -154,6 +193,15 @@ function resolveGenerics(type: Type, scope = new Map<string, GenericType>()): Ty
154
193
  type.parts = type.parts.map((part) => resolveGenerics(part, scope));
155
194
  return type;
156
195
  }
196
+ if (type.kind === 'tuple') {
197
+ for (const element of type.elements) {
198
+ element.type = resolveGenerics(element.type, scope);
199
+ }
200
+ return type;
201
+ }
202
+ if (type.kind === 'reflection') {
203
+ return type;
204
+ }
157
205
  /* c8 ignore next 3 */
158
206
  (type) satisfies never;
159
207
  return type;