Skip to content

Commit

Permalink
Make Logger contravariant over the log type (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fryuni authored Apr 4, 2022
1 parent c4d1705 commit 3a4e57d
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 11 deletions.
6 changes: 3 additions & 3 deletions src/consoleLogger.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import {Log, LogDetails, Logger, LogLevel} from './logger';
import {Log, Logger, LogLevel} from './logger';

/**
* A logger that writes to the console.
*/
export class ConsoleLogger<T extends LogDetails = LogDetails> implements Logger<T> {
export class ConsoleLogger<T extends Log = Log> implements Logger<T> {
private readonly console: Console;

public constructor(targetConsole: Console = console) {
this.console = targetConsole;
}

public log(log: Log<T>): void {
public log(log: T): void {
const args = log.details === undefined
? [log.message]
: [log.message, log.details];
Expand Down
4 changes: 2 additions & 2 deletions src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ export type Log<D extends LogDetails = LogDetails> = {
/**
* A common interface for loggers.
*/
export interface Logger<D extends LogDetails = LogDetails> {
export interface Logger<L extends Log = Log> {
/**
* Logs a message.
*
* @param log The log message.
*/
log(log: Log<D>): void;
log(log: L): void;
}
6 changes: 3 additions & 3 deletions src/prefixedLogger.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {Log, LogDetails, Logger} from './logger';
import {Log, Logger} from './logger';

/**
* A logger that prepends a prefix to all log messages.
*/
export class PrefixedLogger<T extends LogDetails = LogDetails> implements Logger<T> {
export class PrefixedLogger<T extends Log = Log> implements Logger<T> {
/**
* The logger to which messages are forwarded.
*/
Expand All @@ -25,7 +25,7 @@ export class PrefixedLogger<T extends LogDetails = LogDetails> implements Logger
this.prefix = prefix;
}

public log({message, ...log}: Log<T>): void {
public log({message, ...log}: T): void {
this.logger.log({
message: `[${this.prefix}] ${message}`,
...log,
Expand Down
4 changes: 2 additions & 2 deletions src/suppressedLogger.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {LogDetails, Logger} from './logger';
import {Log, Logger} from './logger';

/**
* A logger that suppresses all logging.
*/
export class SuppressedLogger<T extends LogDetails = LogDetails> implements Logger<T> {
export class SuppressedLogger<T extends Log = Log> implements Logger<T> {
public log(): void {
// suppress debug logs
}
Expand Down
17 changes: 17 additions & 0 deletions test/variance.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {Log, Logger} from '../src';

declare function make<T>(): T;

declare function receive<T>(x: T): void;

type TestLog = Log<{
foo: string,
}>;

// Covariance Log test:
// A custom Log type must be assignable to the base logger type.
receive<Log>(make<TestLog>());

// Contravariance Logger test:
// A base logger must be assignable to a logger with a custom Log type.
receive<Logger<TestLog>>(make<Logger>());
2 changes: 1 addition & 1 deletion tsconfig.build.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"exclude": [
"node_modules",
"build",
"**/*.test.ts"
"test/**/*.ts"
]
}

0 comments on commit 3a4e57d

Please sign in to comment.