Inheritance and Generics
Forger resolves types through the TypeScript checker, so inheritance chains and generic substitutions work the way the compiler sees them.
Inheritance
The whole chain is flattened: properties of every ancestor are merged with the properties of the type itself.
interface BaseEntity {
id: number;
createdAt: Date;
}
interface Employee extends BaseEntity {
name: string;
}
const employee = Forger.create<Employee>()!;
// { id: 952, createdAt: Date(…), name: '…' } — id and createdAt included
The same applies to extends in classes and to interface-to-class inheritance.
Generics
Generic arguments are substituted at the call site: Box<number> is resolved as if T were replaced with number everywhere in the declaration.
interface Box<T> {
content: T;
label: string;
}
const box = Forger.create<Box<number>>()!;
// { content: 452, label: '…' }
const stringBox = Forger.create<Box<string>>()!;
// { content: '…', label: '…' }
Multiple type arguments work the same way:
interface Pair<A, B> {
first: A;
second: B;
}
const pair = Forger.create<Pair<string, Date>>()!;
// { first: '…', second: Date(…) }
Generic types nested inside other types (Box<Box<number>>) are resolved recursively.
Inherited generics
A generic type that inherits from another generic resolves after substitution:
interface Entity<T> { id: T }
interface User extends Entity<number> { name: string }
const user = Forger.create<User>()!;
// { id: 417, name: '…' } — id is a number, exactly as Entity<number> declares
Union type arguments
Type arguments may themselves be unions or literal unions — they follow the regular union rules:
const settings = Forger.create<Box<'on' | 'off'>>()!;
// { content: 'on', label: '…' } — or 'off', rolled at runtime
08 September 2026