@tsonic/emitter 0.0.1
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/package.json +34 -0
- package/scripts/update-golden-tests.ts +119 -0
- package/src/adapter-generator.ts +112 -0
- package/src/array.test.ts +301 -0
- package/src/constants.ts +32 -0
- package/src/core/exports.ts +36 -0
- package/src/core/imports.test.ts +83 -0
- package/src/core/imports.ts +243 -0
- package/src/core/index.ts +9 -0
- package/src/core/module-emitter/assembly.ts +83 -0
- package/src/core/module-emitter/header.ts +19 -0
- package/src/core/module-emitter/index.ts +17 -0
- package/src/core/module-emitter/namespace.ts +39 -0
- package/src/core/module-emitter/orchestrator.ts +98 -0
- package/src/core/module-emitter/separation.ts +41 -0
- package/src/core/module-emitter/static-container.ts +75 -0
- package/src/core/module-emitter.test.ts +154 -0
- package/src/core/module-emitter.ts +6 -0
- package/src/core/module-map.ts +218 -0
- package/src/core/options.ts +16 -0
- package/src/core/type-params.ts +34 -0
- package/src/emitter-types/context.ts +91 -0
- package/src/emitter-types/core.ts +138 -0
- package/src/emitter-types/csharp-types.ts +42 -0
- package/src/emitter-types/formatting.ts +13 -0
- package/src/emitter-types/fqn.ts +81 -0
- package/src/emitter-types/index.ts +31 -0
- package/src/emitter.ts +107 -0
- package/src/expression-emitter.ts +112 -0
- package/src/expressions/access.ts +104 -0
- package/src/expressions/calls.ts +264 -0
- package/src/expressions/collections.ts +354 -0
- package/src/expressions/functions.ts +71 -0
- package/src/expressions/identifiers.ts +125 -0
- package/src/expressions/index.test.ts +515 -0
- package/src/expressions/index.ts +38 -0
- package/src/expressions/literals.ts +138 -0
- package/src/expressions/operators.ts +211 -0
- package/src/expressions/other.ts +63 -0
- package/src/generator-exchange.ts +120 -0
- package/src/generator.test.ts +193 -0
- package/src/golden-tests/config-parser.ts +67 -0
- package/src/golden-tests/discovery.ts +61 -0
- package/src/golden-tests/index.ts +10 -0
- package/src/golden-tests/registration.ts +26 -0
- package/src/golden-tests/runner.ts +131 -0
- package/src/golden-tests/tree-builder.ts +43 -0
- package/src/golden-tests/types.ts +21 -0
- package/src/golden.test.ts +40 -0
- package/src/hierarchical-bindings.test.ts +258 -0
- package/src/index.ts +14 -0
- package/src/integration.test.ts +303 -0
- package/src/specialization/call-site-rewriting.test.ts +99 -0
- package/src/specialization/collection/expressions.ts +184 -0
- package/src/specialization/collection/index.ts +7 -0
- package/src/specialization/collection/orchestrator.ts +25 -0
- package/src/specialization/collection/statements.ts +91 -0
- package/src/specialization/collection.ts +10 -0
- package/src/specialization/generation.ts +189 -0
- package/src/specialization/generic-classes.test.ts +59 -0
- package/src/specialization/generic-functions.test.ts +292 -0
- package/src/specialization/helpers.ts +39 -0
- package/src/specialization/index.ts +28 -0
- package/src/specialization/interfaces.test.ts +151 -0
- package/src/specialization/naming.ts +34 -0
- package/src/specialization/substitution.ts +186 -0
- package/src/specialization/type-aliases.test.ts +134 -0
- package/src/specialization/types.ts +19 -0
- package/src/specialization-generator.ts +23 -0
- package/src/statement-emitter.ts +117 -0
- package/src/statements/blocks.ts +115 -0
- package/src/statements/classes/helpers.ts +9 -0
- package/src/statements/classes/index.ts +13 -0
- package/src/statements/classes/inline-types.ts +79 -0
- package/src/statements/classes/members/constructors.ts +123 -0
- package/src/statements/classes/members/index.ts +8 -0
- package/src/statements/classes/members/methods.ts +137 -0
- package/src/statements/classes/members/orchestrator.ts +33 -0
- package/src/statements/classes/members/properties.ts +62 -0
- package/src/statements/classes/members.ts +6 -0
- package/src/statements/classes/parameters.ts +69 -0
- package/src/statements/classes/properties.ts +95 -0
- package/src/statements/classes.ts +14 -0
- package/src/statements/control/conditionals.ts +134 -0
- package/src/statements/control/exceptions.ts +59 -0
- package/src/statements/control/index.ts +11 -0
- package/src/statements/control/loops.ts +250 -0
- package/src/statements/control.ts +14 -0
- package/src/statements/declarations/classes.ts +89 -0
- package/src/statements/declarations/enums.ts +32 -0
- package/src/statements/declarations/functions.ts +147 -0
- package/src/statements/declarations/index.ts +10 -0
- package/src/statements/declarations/interfaces.ts +116 -0
- package/src/statements/declarations/structs.test.ts +182 -0
- package/src/statements/declarations/type-aliases.ts +104 -0
- package/src/statements/declarations/variables.ts +159 -0
- package/src/statements/declarations.ts +13 -0
- package/src/statements/index.test.ts +258 -0
- package/src/statements/index.ts +43 -0
- package/src/type-assertion.test.ts +143 -0
- package/src/type-emitter.ts +18 -0
- package/src/types/arrays.ts +21 -0
- package/src/types/dictionaries.ts +52 -0
- package/src/types/emitter.ts +76 -0
- package/src/types/functions.ts +45 -0
- package/src/types/index.test.ts +116 -0
- package/src/types/index.ts +14 -0
- package/src/types/intersections.ts +19 -0
- package/src/types/literals.ts +26 -0
- package/src/types/objects.ts +27 -0
- package/src/types/parameters.test.ts +146 -0
- package/src/types/parameters.ts +95 -0
- package/src/types/primitives.ts +24 -0
- package/src/types/references.ts +187 -0
- package/src/types/unions.test.ts +397 -0
- package/src/types/unions.ts +62 -0
- package/src/types.ts +33 -0
- package/testcases/README.md +213 -0
- package/testcases/arrays/basic/ArrayLiteral.ts +4 -0
- package/testcases/arrays/basic/config.yaml +1 -0
- package/testcases/arrays/destructuring/ArrayDestructure.ts +4 -0
- package/testcases/arrays/destructuring/config.yaml +1 -0
- package/testcases/arrays/methods/ArrayMethods.ts +6 -0
- package/testcases/arrays/methods/config.yaml +1 -0
- package/testcases/arrays/multidimensional/MultiDimensional.ts +10 -0
- package/testcases/arrays/multidimensional/config.yaml +1 -0
- package/testcases/arrays/spread/ArraySpread.ts +3 -0
- package/testcases/arrays/spread/config.yaml +1 -0
- package/testcases/async/basic/AsyncFunction.ts +5 -0
- package/testcases/async/basic/config.yaml +1 -0
- package/testcases/classes/abstract/AbstractClasses.ts +53 -0
- package/testcases/classes/abstract/config.yaml +1 -0
- package/testcases/classes/basic/Person.ts +12 -0
- package/testcases/classes/basic/config.yaml +1 -0
- package/testcases/classes/constructor/User.ts +11 -0
- package/testcases/classes/constructor/config.yaml +1 -0
- package/testcases/classes/field-inference/Counter.ts +11 -0
- package/testcases/classes/field-inference/config.yaml +1 -0
- package/testcases/classes/inheritance/Inheritance.ts +24 -0
- package/testcases/classes/inheritance/config.yaml +1 -0
- package/testcases/classes/static-members/MathHelper.ts +12 -0
- package/testcases/classes/static-members/config.yaml +1 -0
- package/testcases/control-flow/error-handling/ErrorHandling.ts +13 -0
- package/testcases/control-flow/error-handling/config.yaml +1 -0
- package/testcases/control-flow/loops/Loops.ts +21 -0
- package/testcases/control-flow/loops/config.yaml +1 -0
- package/testcases/control-flow/switch/SwitchStatement.ts +15 -0
- package/testcases/control-flow/switch/config.yaml +1 -0
- package/testcases/edge-cases/complex-expressions/ComplexExpressions.ts +10 -0
- package/testcases/edge-cases/complex-expressions/config.yaml +1 -0
- package/testcases/edge-cases/nested-scopes/NestedScopes.ts +10 -0
- package/testcases/edge-cases/nested-scopes/config.yaml +1 -0
- package/testcases/edge-cases/shadowing/Shadowing.ts +16 -0
- package/testcases/edge-cases/shadowing/config.yaml +1 -0
- package/testcases/functions/arrow/ArrowFunction.ts +5 -0
- package/testcases/functions/arrow/config.yaml +1 -0
- package/testcases/functions/basic/Greet.ts +3 -0
- package/testcases/functions/basic/config.yaml +1 -0
- package/testcases/functions/closures/Closures.ts +11 -0
- package/testcases/functions/closures/config.yaml +1 -0
- package/testcases/functions/default-params/DefaultParams.ts +7 -0
- package/testcases/functions/default-params/config.yaml +1 -0
- package/testcases/functions/rest-params/RestParams.ts +7 -0
- package/testcases/functions/rest-params/config.yaml +1 -0
- package/testcases/functions/type-guards/TypeGuards.ts +52 -0
- package/testcases/functions/type-guards/config.yaml +1 -0
- package/testcases/operators/logical/LogicalOperators.ts +11 -0
- package/testcases/operators/logical/config.yaml +1 -0
- package/testcases/operators/nullish-coalescing/NullishCoalescing.ts +7 -0
- package/testcases/operators/nullish-coalescing/config.yaml +1 -0
- package/testcases/operators/optional-chaining/OptionalChaining.ts +15 -0
- package/testcases/operators/optional-chaining/config.yaml +1 -0
- package/testcases/real-world/advanced-generics/advanced-generics.ts +116 -0
- package/testcases/real-world/advanced-generics/config.yaml +1 -0
- package/testcases/real-world/async-ops/async-ops.ts +67 -0
- package/testcases/real-world/async-ops/config.yaml +1 -0
- package/testcases/real-world/business-logic/business-logic.ts +215 -0
- package/testcases/real-world/business-logic/config.yaml +1 -0
- package/testcases/real-world/calculator/calculator.ts +29 -0
- package/testcases/real-world/calculator/config.yaml +1 -0
- package/testcases/real-world/data-structures/config.yaml +1 -0
- package/testcases/real-world/data-structures/data-structures.ts +133 -0
- package/testcases/real-world/functional/config.yaml +1 -0
- package/testcases/real-world/functional/functional.ts +116 -0
- package/testcases/real-world/shapes/config.yaml +1 -0
- package/testcases/real-world/shapes/shapes.ts +87 -0
- package/testcases/real-world/string-utils/config.yaml +1 -0
- package/testcases/real-world/string-utils/string-utils.ts +47 -0
- package/testcases/real-world/todo-list/config.yaml +1 -0
- package/testcases/real-world/todo-list/todo-list.ts +52 -0
- package/testcases/real-world/type-guards/config.yaml +1 -0
- package/testcases/real-world/type-guards/type-guards.ts +71 -0
- package/testcases/structs/basic/Point.ts +9 -0
- package/testcases/structs/basic/config.yaml +1 -0
- package/testcases/types/conditional/ConditionalTypes.ts +35 -0
- package/testcases/types/conditional/config.yaml +1 -0
- package/testcases/types/constants/ModuleConstants.ts +6 -0
- package/testcases/types/constants/config.yaml +1 -0
- package/testcases/types/generics/Generics.ts +15 -0
- package/testcases/types/generics/config.yaml +1 -0
- package/testcases/types/interfaces/Interfaces.ts +14 -0
- package/testcases/types/interfaces/config.yaml +1 -0
- package/testcases/types/mapped/MappedTypes.ts +27 -0
- package/testcases/types/mapped/config.yaml +1 -0
- package/testcases/types/tuples-intersections/TuplesAndIntersections.ts +46 -0
- package/testcases/types/tuples-intersections/config.yaml +1 -0
- package/testcases/types/unions/UnionTypes.ts +11 -0
- package/testcases/types/unions/config.yaml +1 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- ArrayLiteral.ts: should emit basic array literal with correct type
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- ArrayDestructure.ts: should emit array destructuring with element access
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- ArrayMethods.ts: should emit array method calls (map, filter, reduce)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- MultiDimensional.ts: should emit multi-dimensional array access
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- ArraySpread.ts: should emit array spread operator
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- AsyncFunction.ts: should emit async function with Promise<string> return type
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Abstract base class
|
|
2
|
+
export abstract class Shape {
|
|
3
|
+
abstract getArea(): number;
|
|
4
|
+
abstract getPerimeter(): number;
|
|
5
|
+
|
|
6
|
+
// Concrete method in abstract class
|
|
7
|
+
describe(): string {
|
|
8
|
+
return `Area: ${this.getArea()}, Perimeter: ${this.getPerimeter()}`;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Concrete implementation
|
|
13
|
+
export class Rectangle extends Shape {
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
|
|
17
|
+
constructor(width: number, height: number) {
|
|
18
|
+
super();
|
|
19
|
+
this.width = width;
|
|
20
|
+
this.height = height;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
getArea(): number {
|
|
24
|
+
return this.width * this.height;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
getPerimeter(): number {
|
|
28
|
+
return 2 * (this.width + this.height);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Another concrete implementation
|
|
33
|
+
export class Circle extends Shape {
|
|
34
|
+
radius: number;
|
|
35
|
+
|
|
36
|
+
constructor(radius: number) {
|
|
37
|
+
super();
|
|
38
|
+
this.radius = radius;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getArea(): number {
|
|
42
|
+
return Math.PI * this.radius * this.radius;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
getPerimeter(): number {
|
|
46
|
+
return 2 * Math.PI * this.radius;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Function using abstract class
|
|
51
|
+
export function calculateTotalArea(shapes: Shape[]): number {
|
|
52
|
+
return shapes.reduce((total, shape) => total + shape.getArea(), 0);
|
|
53
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- AbstractClasses.ts: should emit abstract classes with abstract methods
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- Person.ts: should emit basic class with methods
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- User.ts: should emit class constructor with parameter properties
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- Counter.ts: should infer CLR types for class fields without type annotations
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export class Animal {
|
|
2
|
+
name: string;
|
|
3
|
+
|
|
4
|
+
constructor(name: string) {
|
|
5
|
+
this.name = name;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
makeSound(): string {
|
|
9
|
+
return "Some sound";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class Dog extends Animal {
|
|
14
|
+
breed: string;
|
|
15
|
+
|
|
16
|
+
constructor(name: string, breed: string) {
|
|
17
|
+
super(name);
|
|
18
|
+
this.breed = breed;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
makeSound(): string {
|
|
22
|
+
return "Woof!";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- Inheritance.ts: should emit class inheritance with extends keyword
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- MathHelper.ts: should emit static properties and methods
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function safeDivide(a: number, b: number): number {
|
|
2
|
+
try {
|
|
3
|
+
if (b === 0) {
|
|
4
|
+
throw new Error("Division by zero");
|
|
5
|
+
}
|
|
6
|
+
return a / b;
|
|
7
|
+
} catch (error) {
|
|
8
|
+
console.log(error);
|
|
9
|
+
return 0;
|
|
10
|
+
} finally {
|
|
11
|
+
console.log("Operation complete");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- ErrorHandling.ts: should emit try-catch-finally blocks
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function sumEven(numbers: number[]): number {
|
|
2
|
+
let sum = 0;
|
|
3
|
+
for (let i = 0; i < numbers.length; i++) {
|
|
4
|
+
if (numbers[i] % 2 !== 0) {
|
|
5
|
+
continue;
|
|
6
|
+
}
|
|
7
|
+
sum += numbers[i];
|
|
8
|
+
}
|
|
9
|
+
return sum;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function findFirst(numbers: number[], target: number): number {
|
|
13
|
+
let i = 0;
|
|
14
|
+
while (i < numbers.length) {
|
|
15
|
+
if (numbers[i] === target) {
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
i++;
|
|
19
|
+
}
|
|
20
|
+
return i;
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- Loops.ts: should emit for, while loops with break and continue
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- SwitchStatement.ts: should emit switch statement with cases and default
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function complexExpression(a: number, b: number, c: number): number {
|
|
2
|
+
return (a + b) * c - a / b + (c % a) * ((b - a) / (c + 1));
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function chainedCalls(arr: number[]): number {
|
|
6
|
+
return arr
|
|
7
|
+
.map((x) => x * 2)
|
|
8
|
+
.filter((x) => x > 10)
|
|
9
|
+
.reduce((acc, x) => acc + x, 0);
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- ComplexExpressions.ts: should handle deeply nested and complex expressions
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- NestedScopes.ts: should handle nested block scopes correctly
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function shadowedVariable(): number {
|
|
2
|
+
const x = 10;
|
|
3
|
+
{
|
|
4
|
+
const x = 20;
|
|
5
|
+
return x;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function shadowInFunction(): number {
|
|
10
|
+
const value = 5;
|
|
11
|
+
const inner = (): number => {
|
|
12
|
+
const value = 10;
|
|
13
|
+
return value;
|
|
14
|
+
};
|
|
15
|
+
return value + inner();
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- Shadowing.ts: should handle variable shadowing correctly
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- ArrowFunction.ts: should emit arrow function as lambda expression
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- Greet.ts: should emit simple function with string parameter
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- Closures.ts: should emit closure capturing outer scope variables
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- DefaultParams.ts: should emit function with default parameter values
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- RestParams.ts: should emit function with rest parameters as params array
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface Dog {
|
|
2
|
+
type: "dog";
|
|
3
|
+
bark(): void;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface Cat {
|
|
7
|
+
type: "cat";
|
|
8
|
+
meow(): void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type Animal = Dog | Cat;
|
|
12
|
+
|
|
13
|
+
// Type guard function with 'is' predicate
|
|
14
|
+
export function isDog(animal: Animal): animal is Dog {
|
|
15
|
+
return animal.type === "dog";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function isCat(animal: Animal): animal is Cat {
|
|
19
|
+
return animal.type === "cat";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Using type guards
|
|
23
|
+
export function makeSound(animal: Animal): void {
|
|
24
|
+
if (isDog(animal)) {
|
|
25
|
+
animal.bark();
|
|
26
|
+
} else if (isCat(animal)) {
|
|
27
|
+
animal.meow();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// typeof type guard
|
|
32
|
+
export function processValue(value: string | number): string {
|
|
33
|
+
if (typeof value === "string") {
|
|
34
|
+
return value.toUpperCase();
|
|
35
|
+
}
|
|
36
|
+
return value.toString();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// instanceof type guard
|
|
40
|
+
export class Circle {
|
|
41
|
+
radius: number;
|
|
42
|
+
constructor(radius: number) {
|
|
43
|
+
this.radius = radius;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function getArea(shape: Circle | number): number {
|
|
48
|
+
if (shape instanceof Circle) {
|
|
49
|
+
return Math.PI * shape.radius * shape.radius;
|
|
50
|
+
}
|
|
51
|
+
return shape;
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- TypeGuards.ts: should emit type guard functions with is predicates
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function isValid(name: string, age: number): boolean {
|
|
2
|
+
return name.length > 0 && age >= 18;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function getDisplayName(name: string | null): string {
|
|
6
|
+
return name || "Anonymous";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function classify(age: number): string {
|
|
10
|
+
return age >= 18 ? "adult" : "minor";
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- LogicalOperators.ts: should emit logical operators (&&, ||, ternary)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- NullishCoalescing.ts: should emit nullish coalescing operator (??)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface User {
|
|
2
|
+
name?: string;
|
|
3
|
+
address?: {
|
|
4
|
+
street?: string;
|
|
5
|
+
city?: string;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function getCity(user: User | null): string | undefined {
|
|
10
|
+
return user?.address?.city;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function getNameLength(user: User | null): number {
|
|
14
|
+
return user?.name?.length ?? 0;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- OptionalChaining.ts: should emit optional chaining operator (?.)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Generic pair
|
|
2
|
+
export class Pair<T, U> {
|
|
3
|
+
constructor(
|
|
4
|
+
public first: T,
|
|
5
|
+
public second: U
|
|
6
|
+
) {}
|
|
7
|
+
|
|
8
|
+
swap(): Pair<U, T> {
|
|
9
|
+
return new Pair(this.second, this.first);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
map<V, W>(
|
|
13
|
+
firstMapper: (value: T) => V,
|
|
14
|
+
secondMapper: (value: U) => W
|
|
15
|
+
): Pair<V, W> {
|
|
16
|
+
return new Pair(firstMapper(this.first), secondMapper(this.second));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Generic result type
|
|
21
|
+
export type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
|
|
22
|
+
|
|
23
|
+
export function ok<T, E>(value: T): Result<T, E> {
|
|
24
|
+
return { ok: true, value };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function err<T, E>(error: E): Result<T, E> {
|
|
28
|
+
return { ok: false, error };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function isOk<T, E>(
|
|
32
|
+
result: Result<T, E>
|
|
33
|
+
): result is { ok: true; value: T } {
|
|
34
|
+
return result.ok === true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function isErr<T, E>(
|
|
38
|
+
result: Result<T, E>
|
|
39
|
+
): result is { ok: false; error: E } {
|
|
40
|
+
return result.ok === false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Generic tree structure
|
|
44
|
+
export class TreeNode<T> {
|
|
45
|
+
children: TreeNode<T>[] = [];
|
|
46
|
+
|
|
47
|
+
constructor(public value: T) {}
|
|
48
|
+
|
|
49
|
+
addChild(value: T): TreeNode<T> {
|
|
50
|
+
const child = new TreeNode(value);
|
|
51
|
+
this.children.push(child);
|
|
52
|
+
return child;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
forEach(callback: (value: T) => void): void {
|
|
56
|
+
callback(this.value);
|
|
57
|
+
for (const child of this.children) {
|
|
58
|
+
child.forEach(callback);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
map<U>(mapper: (value: T) => U): TreeNode<U> {
|
|
63
|
+
const mapped = new TreeNode(mapper(this.value));
|
|
64
|
+
for (const child of this.children) {
|
|
65
|
+
mapped.children.push(child.map(mapper));
|
|
66
|
+
}
|
|
67
|
+
return mapped;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Constrained generics
|
|
72
|
+
export interface Comparable<T> {
|
|
73
|
+
compareTo(other: T): number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function min<T extends Comparable<T>>(items: T[]): T | undefined {
|
|
77
|
+
if (items.length === 0) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let result = items[0];
|
|
82
|
+
for (let i = 1; i < items.length; i++) {
|
|
83
|
+
if (items[i].compareTo(result) < 0) {
|
|
84
|
+
result = items[i];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function max<T extends Comparable<T>>(items: T[]): T | undefined {
|
|
91
|
+
if (items.length === 0) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let result = items[0];
|
|
96
|
+
for (let i = 1; i < items.length; i++) {
|
|
97
|
+
if (items[i].compareTo(result) > 0) {
|
|
98
|
+
result = items[i];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Generic builder pattern
|
|
105
|
+
export class Builder<T> {
|
|
106
|
+
private props: Partial<T> = {};
|
|
107
|
+
|
|
108
|
+
set<K extends keyof T>(key: K, value: T[K]): Builder<T> {
|
|
109
|
+
this.props[key] = value;
|
|
110
|
+
return this;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
build(): T {
|
|
114
|
+
return this.props as T;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- advanced-generics.ts: should emit real-world advanced-generics program
|