+22
-10
packages/emitter/src/emitter.ts
+22
-10
packages/emitter/src/emitter.ts
···
48
48
LexCidLink,
49
49
LexRefVariant,
50
50
LexToken,
51
+
LexBoolean,
52
+
LexInteger,
53
+
LexString,
51
54
} from "./types.js";
52
55
53
56
import {
···
415
418
// Apply @default decorator if present
416
419
const rawDefault = getDefault(this.program, scalar);
417
420
const defaultValue = this.processDefaultValue(rawDefault);
418
-
let defWithDefault: any = { ...scalarDef };
421
+
let defWithDefault: LexObjectProperty = { ...scalarDef };
419
422
420
423
if (defaultValue !== undefined) {
421
424
// Check if it's a Type (model reference for tokens)
···
431
434
} else {
432
435
// Validate that the default value matches the type
433
436
this.assertValidValueForType(scalarDef.type, defaultValue, scalar);
434
-
defWithDefault = { ...defWithDefault, default: defaultValue };
437
+
// Type-safe narrowing based on both the type discriminator and value type
438
+
if (scalarDef.type === "boolean" && typeof defaultValue === "boolean") {
439
+
(defWithDefault as LexBoolean).default = defaultValue;
440
+
} else if (scalarDef.type === "integer" && typeof defaultValue === "number") {
441
+
(defWithDefault as LexInteger).default = defaultValue;
442
+
} else if (scalarDef.type === "string" && typeof defaultValue === "string") {
443
+
(defWithDefault as LexString).default = defaultValue;
444
+
}
435
445
}
436
446
}
437
447
···
439
449
if (scalarDef.type === "integer") {
440
450
const minValue = getMinValue(this.program, scalar);
441
451
if (minValue !== undefined) {
442
-
(defWithDefault as any).minimum = minValue;
452
+
(defWithDefault as LexInteger).minimum = minValue;
443
453
}
444
454
const maxValue = getMaxValue(this.program, scalar);
445
455
if (maxValue !== undefined) {
446
-
(defWithDefault as any).maximum = maxValue;
456
+
(defWithDefault as LexInteger).maximum = maxValue;
447
457
}
448
458
}
449
459
···
474
484
// Apply @default decorator if present
475
485
const rawDefault = getDefault(this.program, union);
476
486
const defaultValue = this.processDefaultValue(rawDefault);
477
-
let defWithDefault: any = { ...unionDef };
487
+
let defWithDefault: LexString = { ...unionDef as LexString };
478
488
479
489
if (defaultValue !== undefined) {
480
490
// Check if it's a Type (model reference for tokens)
···
517
527
`Use @inline to inline them at usage sites, use @token models for known values, or use string literals.`,
518
528
target: union,
519
529
});
520
-
} else if (unionDef.type === "integer" && (unionDef as any).enum) {
530
+
} else if (unionDef.type === "integer" && (unionDef as LexInteger).enum) {
521
531
// Integer enums can also be defs
522
532
const defName = name.charAt(0).toLowerCase() + name.slice(1);
523
533
const description = getDoc(this.program, union);
···
525
535
// Apply @default decorator if present
526
536
const rawDefault = getDefault(this.program, union);
527
537
const defaultValue = this.processDefaultValue(rawDefault);
528
-
let defWithDefault = { ...unionDef };
538
+
let defWithDefault: LexInteger = { ...unionDef as LexInteger };
529
539
530
540
if (defaultValue !== undefined) {
531
541
if (typeof defaultValue === "number") {
···
645
655
// Check for default value: property default takes precedence, then union's @default
646
656
let defaultValue: string | number | boolean | undefined;
647
657
if (prop?.defaultValue !== undefined) {
648
-
defaultValue = serializeValueAsJson(this.program, prop.defaultValue, prop) as any;
658
+
defaultValue = serializeValueAsJson(this.program, prop.defaultValue, prop) as string | number | boolean;
649
659
} else {
650
660
// If no property default, check union's @default decorator
651
661
const rawUnionDefault = getDefault(this.program, unionType);
···
681
691
// Check for default value: property default takes precedence, then union's @default
682
692
let defaultValue: string | number | boolean | undefined;
683
693
if (prop?.defaultValue !== undefined) {
684
-
defaultValue = serializeValueAsJson(this.program, prop.defaultValue, prop) as any;
694
+
defaultValue = serializeValueAsJson(this.program, prop.defaultValue, prop) as string | number | boolean;
685
695
} else {
686
696
// If no property default, check union's @default decorator
687
697
const rawUnionDefault = getDefault(this.program, unionType);
···
1452
1462
const propDefault = serializeValueAsJson(this.program, prop.defaultValue, prop);
1453
1463
1454
1464
// For union defaults that are model references, we need to resolve them for comparison
1455
-
let resolvedUnionDefault: string | number | boolean | undefined = unionDefault as any;
1465
+
let resolvedUnionDefault: string | number | boolean | undefined;
1456
1466
if (unionDefault && typeof unionDefault === 'object' && 'kind' in unionDefault && unionDefault.kind === 'Model') {
1457
1467
const ref = this.getModelReference(unionDefault as Model, true);
1458
1468
resolvedUnionDefault = ref || undefined;
1469
+
} else {
1470
+
resolvedUnionDefault = unionDefault as string | number | boolean;
1459
1471
}
1460
1472
1461
1473
// If the union has a different default, or if the property has a default but the union doesn't, error