@mirascript/typed 0.1.63 → 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/README.md +38 -27
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/json.d.ts +2 -2
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +100 -43
- package/dist/json.js.map +1 -1
- package/dist/parser.d.ts +29 -1
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +13 -0
- package/dist/parser.js.map +1 -1
- package/dist/simplifier.d.ts +25 -0
- package/dist/simplifier.d.ts.map +1 -0
- package/dist/simplifier.js +274 -0
- package/dist/simplifier.js.map +1 -0
- package/dist/stringify.d.ts +7 -0
- package/dist/stringify.d.ts.map +1 -0
- package/dist/stringify.js +186 -0
- package/dist/stringify.js.map +1 -0
- package/dist/type.js +601 -289
- package/dist/type.js.map +1 -1
- package/package.json +7 -6
- package/src/index.ts +2 -0
- package/src/json.ts +109 -55
- package/src/parser.ts +50 -11
- package/src/simplifier.ts +327 -0
- package/src/stringify.ts +191 -0
- package/src/type.peggy +49 -2
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":";;;;;AAAEA;AACFA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;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","file":"type.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mirascript/typed",
|
|
3
|
-
"version": "0.1.
|
|
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.
|
|
26
|
+
"@types/node": "^26.1.1",
|
|
27
27
|
"ava": "^8.0.1",
|
|
28
28
|
"c8": "^11.0.0",
|
|
29
|
-
"js-yaml": "^5.2.
|
|
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
|
-
"
|
|
34
|
-
"@mirascript/constants": "~0.1.
|
|
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
package/src/json.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type {
|
|
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):
|
|
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):
|
|
108
|
-
|
|
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[]):
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
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
|
|
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):
|
|
135
|
+
export function toJSONSchema(type: Type, options?: ToJSONSchemaOptions): JSONSchema {
|
|
138
136
|
const loose = options?.loose ?? false;
|
|
139
|
-
|
|
137
|
+
const simplified = simplify(type);
|
|
138
|
+
if (typeof simplified == 'symbol') {
|
|
140
139
|
return {};
|
|
141
140
|
}
|
|
142
|
-
if (typeof
|
|
143
|
-
return string(
|
|
141
|
+
if (typeof simplified == 'string') {
|
|
142
|
+
return string(simplified);
|
|
144
143
|
}
|
|
145
|
-
if (
|
|
144
|
+
if (simplified.kind === 'array') {
|
|
146
145
|
return {
|
|
147
146
|
type: 'array',
|
|
148
|
-
items: toJSONSchema(
|
|
147
|
+
items: toJSONSchema(simplified.element, options),
|
|
149
148
|
};
|
|
150
149
|
}
|
|
151
|
-
if (
|
|
152
|
-
const anyOf = [];
|
|
153
|
-
const literals = [];
|
|
154
|
-
for (const t of
|
|
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 (
|
|
170
|
-
|
|
171
|
-
|
|
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
|
|
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:
|
|
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(
|
|
191
|
-
if (
|
|
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
|
|
198
|
-
if (isLiteralType(
|
|
199
|
-
const schema:
|
|
203
|
+
if (typeof simplified.key == 'object') {
|
|
204
|
+
if (isLiteralType(simplified.key)) {
|
|
205
|
+
const schema: JSONSchema = {
|
|
200
206
|
type: 'object',
|
|
201
|
-
properties: { [String(
|
|
207
|
+
properties: { [String(simplified.key.value)]: valueSchema },
|
|
202
208
|
additionalProperties: loose,
|
|
203
209
|
};
|
|
204
210
|
return schema;
|
|
205
|
-
} else if (
|
|
206
|
-
const schema:
|
|
211
|
+
} else if (simplified.key.kind === 'union' && simplified.key.types.every(isLiteralType)) {
|
|
212
|
+
const schema: JSONSchema = {
|
|
207
213
|
type: 'object',
|
|
208
|
-
properties: Object.fromEntries(
|
|
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(
|
|
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:
|
|
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 (
|
|
229
|
-
return literal(
|
|
234
|
+
if (simplified.kind === 'literal') {
|
|
235
|
+
return literal(simplified);
|
|
230
236
|
}
|
|
231
|
-
if (
|
|
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 (
|
|
235
|
-
return
|
|
288
|
+
if (simplified.kind === 'reflection') {
|
|
289
|
+
return true;
|
|
236
290
|
}
|
|
237
291
|
/* c8 ignore next 3 */
|
|
238
|
-
|
|
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;
|
|
@@ -33,16 +36,7 @@ export interface TemplateType {
|
|
|
33
36
|
|
|
34
37
|
/** Known type names in MiraScript */
|
|
35
38
|
export type KnownType =
|
|
36
|
-
| '
|
|
37
|
-
| 'number'
|
|
38
|
-
| 'boolean'
|
|
39
|
-
| 'nil'
|
|
40
|
-
| 'array'
|
|
41
|
-
| 'record'
|
|
42
|
-
| 'extern'
|
|
43
|
-
| 'any'
|
|
44
|
-
| 'unknown'
|
|
45
|
-
| 'never';
|
|
39
|
+
'string' | 'number' | 'boolean' | 'nil' | 'array' | 'record' | 'extern' | 'any' | 'unknown' | 'never';
|
|
46
40
|
|
|
47
41
|
/** Named type in MiraScript */
|
|
48
42
|
export type NamedType = string & Record<never, never>;
|
|
@@ -55,6 +49,14 @@ export interface UnionType {
|
|
|
55
49
|
types: Type[];
|
|
56
50
|
}
|
|
57
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
|
+
|
|
58
60
|
/** Array type in MiraScript */
|
|
59
61
|
export interface ArrayType {
|
|
60
62
|
/** Tag */
|
|
@@ -114,6 +116,30 @@ export interface FunctionParameter {
|
|
|
114
116
|
spread?: boolean;
|
|
115
117
|
}
|
|
116
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
|
+
|
|
117
143
|
/**
|
|
118
144
|
* Replaces generic type parameter names in the AST with unique symbols,
|
|
119
145
|
* scoped per function declaration.
|
|
@@ -145,6 +171,10 @@ function resolveGenerics(type: Type, scope = new Map<string, GenericType>()): Ty
|
|
|
145
171
|
type.types = type.types.map((t) => resolveGenerics(t, scope));
|
|
146
172
|
return type;
|
|
147
173
|
}
|
|
174
|
+
if (type.kind === 'intersection') {
|
|
175
|
+
type.types = type.types.map((t) => resolveGenerics(t, scope));
|
|
176
|
+
return type;
|
|
177
|
+
}
|
|
148
178
|
if (type.kind === 'record') {
|
|
149
179
|
if ('fields' in type) {
|
|
150
180
|
for (const field of type.fields) {
|
|
@@ -163,6 +193,15 @@ function resolveGenerics(type: Type, scope = new Map<string, GenericType>()): Ty
|
|
|
163
193
|
type.parts = type.parts.map((part) => resolveGenerics(part, scope));
|
|
164
194
|
return type;
|
|
165
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
|
+
}
|
|
166
205
|
/* c8 ignore next 3 */
|
|
167
206
|
(type) satisfies never;
|
|
168
207
|
return type;
|