Comprehensive TypeScript guidance covering compiler configuration, advanced types, utility types, type guards, strict mode workflows, and documentation patterns; use when configuring tsconfig, designing complex generics, making illegal states unrepresentable, fixing type errors, or writing testable and maintainable type-safe APIs.
Overall
score
99%
Does it follow best practices?
Validation for skill structure
Implement type-safe dependency injection for testable, maintainable code.
type ServiceFactory<T> = () => T;
type ServiceIdentifier<T> = symbol & { __type?: T };
class Container {
private services = new Map<symbol, ServiceFactory<any>>();
register<T>(id: ServiceIdentifier<T>, factory: ServiceFactory<T>): void {
this.services.set(id, factory);
}
resolve<T>(id: ServiceIdentifier<T>): T {
const factory = this.services.get(id);
if (!factory) {
throw new Error(`Service not registered: ${id.toString()}`);
}
return factory();
}
}
// Service identifiers
const DATABASE_SERVICE = Symbol('database') as ServiceIdentifier<Database>;
const USER_SERVICE = Symbol('user') as ServiceIdentifier<UserService>;
// Registration
const container = new Container();
container.register(DATABASE_SERVICE, () => new Database());
container.register(USER_SERVICE, () => {
const db = container.resolve(DATABASE_SERVICE);
return new UserService(db);
});
// Resolution
const userService = container.resolve(USER_SERVICE);interface Database {
query<T>(sql: string): Promise<T[]>;
}
interface Logger {
log(message: string): void;
}
class UserRepository {
constructor(
private readonly db: Database,
private readonly logger: Logger
) {}
async findById(id: string) {
this.logger.log(`Finding user: ${id}`);
return this.db.query(`SELECT * FROM users WHERE id = ?`);
}
}
// DI Container provides dependencies
const db: Database = createDatabase();
const logger: Logger = createLogger();
const userRepo = new UserRepository(db, logger);interface InjectionToken<T> {
readonly _type?: T;
}
function createToken<T>(description: string): InjectionToken<T> {
return { _type: undefined } as InjectionToken<T>;
}
const DB_TOKEN = createToken<Database>('Database');
const LOGGER_TOKEN = createToken<Logger>('Logger');
const USER_REPO_TOKEN = createToken<UserRepository>('UserRepository');
class TypedContainer {
private providers = new Map<InjectionToken<any>, any>();
provide<T>(token: InjectionToken<T>, value: T): void {
this.providers.set(token, value);
}
inject<T>(token: InjectionToken<T>): T {
const value = this.providers.get(token);
if (!value) {
throw new Error('Token not provided');
}
return value;
}
}
// Usage
const container = new TypedContainer();
container.provide(DB_TOKEN, createDatabase());
container.provide(LOGGER_TOKEN, createLogger());
container.provide(
USER_REPO_TOKEN,
new UserRepository(
container.inject(DB_TOKEN),
container.inject(LOGGER_TOKEN)
)
);type ServiceLifetime = 'singleton' | 'transient' | 'scoped';
interface ServiceDescriptor<T> {
lifetime: ServiceLifetime;
factory: ServiceFactory<T>;
instance?: T;
}
class ScopedContainer {
private descriptors = new Map<symbol, ServiceDescriptor<any>>();
private scopeInstances = new Map<symbol, any>();
register<T>(
id: symbol,
factory: ServiceFactory<T>,
lifetime: ServiceLifetime = 'transient'
): void {
this.descriptors.set(id, { lifetime, factory });
}
resolve<T>(id: symbol): T {
const descriptor = this.descriptors.get(id);
if (!descriptor) {
throw new Error('Service not registered');
}
switch (descriptor.lifetime) {
case 'singleton':
if (!descriptor.instance) {
descriptor.instance = descriptor.factory();
}
return descriptor.instance;
case 'scoped':
if (!this.scopeInstances.has(id)) {
this.scopeInstances.set(id, descriptor.factory());
}
return this.scopeInstances.get(id);
case 'transient':
return descriptor.factory();
}
}
createScope(): ScopedContainer {
const scope = new ScopedContainer();
scope.descriptors = this.descriptors;
return scope;
}
}// Production
class RealDatabase implements Database {
async query<T>(sql: string): Promise<T[]> {
// Real database query
return [];
}
}
// Test
class MockDatabase implements Database {
queries: string[] = [];
async query<T>(sql: string): Promise<T[]> {
this.queries.push(sql);
return [] as T[];
}
}
// Test setup
const mockDb = new MockDatabase();
const logger = createLogger();
const userRepo = new UserRepository(mockDb, logger);
await userRepo.findById('123');
expect(mockDb.queries).toContain('SELECT * FROM users WHERE id = ?');Install with Tessl CLI
npx tessl i pantheon-ai/typescript-advanced@0.1.1references