Skip to content

Commit

Permalink
feat(trait): support static trait implementation
Browse files Browse the repository at this point in the history
- Refactored trait system to support static trait methods
- Added defaultVal helper function for Default trait
- Improved type safety for trait implementations
- Bumped version to 0.1.6
  • Loading branch information
illuxiza committed Dec 18, 2024
1 parent b062cae commit 2c2fa22
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 107 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rustable",
"version": "0.1.5",
"version": "0.1.6",
"workspaces": [
"packages/*"
],
Expand Down
2 changes: 1 addition & 1 deletion packages/coll/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rustable/coll",
"version": "0.1.5",
"version": "0.1.6",
"description": "Rust-inspired collection types for TypeScript: HashMap, HashSet, and Vec with type safety and efficient implementations",
"keywords": [
"typescript",
Expand Down
2 changes: 1 addition & 1 deletion packages/enum/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rustable/enum",
"version": "0.1.5",
"version": "0.1.6",
"description": "Rust-inspired pattern matching and type-safe error handling for TypeScript. Includes Option<T> for null-safety and Result<T, E> for error handling, with comprehensive pattern matching support",
"keywords": [
"typescript",
Expand Down
2 changes: 1 addition & 1 deletion packages/iter/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rustable/iter",
"version": "0.1.5",
"version": "0.1.6",
"description": "Rust-style iterator adapters for TypeScript, providing a rich set of functional operations for iterating over collections",
"keywords": [
"iterator",
Expand Down
2 changes: 1 addition & 1 deletion packages/trait-impls/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rustable/trait-impls",
"version": "0.1.5",
"version": "0.1.6",
"description": "A TypeScript implementation of Rust-like traits system, providing Clone, Eq, and From traits for type-safe operations. Zero dependencies, fully type-safe.",
"keywords": [
"typescript",
Expand Down
12 changes: 8 additions & 4 deletions packages/trait-impls/src/default.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { trait, useTrait } from '@rustable/trait';
import { Constructor } from '@rustable/utils';
import { trait } from '@rustable/trait';

/**
* Default trait for default value initialization.
Expand All @@ -24,9 +24,13 @@ import { trait } from '@rustable/trait';
@trait
export class Default {
static default<T>(): T {
if (typeof this !== 'function') {
throw new Error('Invalid target type');
}
return new this() as T;
}
}

export function defaultVal<T extends object>(
target: Constructor<T>,
generic?: Constructor<any> | Constructor<any>[],
): T {
return useTrait(target, Default, generic).default<T>();
}
23 changes: 11 additions & 12 deletions packages/trait-impls/src/from.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import { hasTrait, implTrait, trait, TraitImplementation, useTrait } from '@rust
* @template T The type to convert from
*/
@trait
export class From<T = any> {
export class From {
/**
* Creates a new instance of this type from the provided value.
* Must be implemented by types that want to support conversion.
Expand All @@ -51,7 +51,7 @@ export class From<T = any> {
* @returns The converted value
* @throws {Error} If conversion is not implemented
*/
from(_value: T): any {
static from<T>(_value: T): any {
throw new Error('Not implemented');
}
}
Expand Down Expand Up @@ -102,7 +102,6 @@ export function from<T, U extends object>(source: T, targetType: Constructor<U>)
if (typeof targetType !== 'function' || !targetType.prototype) {
throw new Error('Invalid target type');
}
const instance = new targetType();
let wrapped: any = source;
if (typeof source === 'string') {
wrapped = String(source);
Expand All @@ -112,36 +111,36 @@ export function from<T, U extends object>(source: T, targetType: Constructor<U>)
wrapped = Boolean(source);
}
const sourceType = wrapped.constructor as Constructor<T>;
const impl = useTrait(instance, From, sourceType);
return (impl as From<T>).from(source);
const impl = useTrait(targetType, From, sourceType);
return impl.from(source);
}

export function implFrom<T extends object, U extends object>(
sourceType: Constructor<T>,
targetType: Constructor<U>,
implementation: TraitImplementation<T, From<U>>,
implementation: TraitImplementation<T, From, typeof From>,
): void;
export function implFrom<T extends object, U extends object>(
sourceType: Constructor<T>,
targetType: Constructor<U>,
generic: Constructor<any>,
implementation: TraitImplementation<T, From<U>>,
implementation: TraitImplementation<T, From, typeof From>,
): void;
export function implFrom<T extends object, U extends object>(
sourceType: Constructor<T>,
targetType: Constructor<U>,
generic: Constructor<any>[],
implementation: TraitImplementation<T, From<U>>,
implementation: TraitImplementation<T, From, typeof From>,
): void;
export function implFrom<T extends object, U extends object>(
targetType: Constructor<T>,
sourceType: Constructor<U>,
generic: Constructor<any> | Constructor<any>[] | TraitImplementation<T, From<U>>,
implementation?: TraitImplementation<T, From<U>>,
generic: Constructor<any> | Constructor<any>[] | TraitImplementation<T, From, typeof From>,
implementation?: TraitImplementation<T, From, typeof From>,
): void {
// Handle generic parameters
let genericParams = [sourceType];
let actualImplementation: TraitImplementation<T, From<U>> | undefined;
let actualImplementation: TraitImplementation<T, From, typeof From> | undefined;
if (implementation) {
actualImplementation = implementation;
if (Array.isArray(generic)) {
Expand All @@ -155,7 +154,7 @@ export function implFrom<T extends object, U extends object>(
throw new Error('Invalid generic parameter');
}
} else if (generic && typeof generic === 'object') {
actualImplementation = generic as TraitImplementation<T, From<U>>;
actualImplementation = generic as TraitImplementation<T, From, typeof From>;
} else {
throw new Error('Invalid implementation');
}
Expand Down
10 changes: 5 additions & 5 deletions packages/trait-impls/test/default.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Default } from '../src/default';
import { derive, useTraitStatic } from '@rustable/trait';
import { derive } from '@rustable/trait';
import { Default, defaultVal } from '../src/default';

describe('Default trait', () => {
test('should create default instance for primitive types', () => {
Expand All @@ -8,7 +8,7 @@ describe('Default trait', () => {
constructor(public value: number = 0) {}
}

const defaultInstance = useTraitStatic(PrimitiveWrapper, Default).default<PrimitiveWrapper>();
const defaultInstance = defaultVal(PrimitiveWrapper);
expect(defaultInstance.value).toBe(0);
});

Expand All @@ -22,7 +22,7 @@ describe('Default trait', () => {
}
}

const defaultInstance = useTraitStatic(CustomDefault, Default).default<CustomDefault>();
const defaultInstance = defaultVal(CustomDefault);
expect(defaultInstance.name).toBe('Default Name');
});

Expand All @@ -37,7 +37,7 @@ describe('Default trait', () => {
) {}
}

const defaultInstance = useTraitStatic(ComplexType, Default).default<ComplexType>();
const defaultInstance = defaultVal(ComplexType);
expect(defaultInstance.str).toBe('');
expect(defaultInstance.num).toBe(0);
expect(defaultInstance.bool).toBe(false);
Expand Down
2 changes: 1 addition & 1 deletion packages/trait/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rustable/trait",
"version": "0.1.5",
"version": "0.1.6",
"description": "Powerful TypeScript implementation of Rust-like traits. Features type-safe interface definitions, generic traits, multiple implementations, default methods, and runtime trait checking. Perfect for building flexible and maintainable TypeScript applications with Rust-inspired patterns.",
"keywords": [
"typescript",
Expand Down
Loading

0 comments on commit 2c2fa22

Please sign in to comment.