Hone logo
Hone
Problems

Instance Type Helper in TypeScript

This challenge asks you to create a TypeScript utility function that infers the type of an instance of a constructor function. This is useful when you need to work with objects created from a class or constructor without knowing the exact type beforehand, allowing for more flexible and generic code. The helper should accurately determine the instance type based on the constructor provided.

Problem Description

You need to implement a function called instanceTypeOf that takes a constructor function as input and returns its instance type. The constructor function can be a class constructor or a regular function used as a constructor. The function should correctly infer the type of the object that would be created by calling the constructor with new.

Key Requirements:

  • The function must accept a constructor function as its sole argument.
  • The function must return the instance type of the constructor.
  • The function should handle both class constructors and regular function constructors.
  • The return type should be a TypeScript type, not a runtime value.

Expected Behavior:

When called with a constructor, instanceTypeOf should return the type of the object that would be created when new is applied to that constructor.

Edge Cases to Consider:

  • Constructors that take arguments. The type should still reflect the instance type, regardless of constructor arguments.
  • Constructors that return a different type than their instance type (though this is less common, it's good to consider).
  • Constructors that are not actually constructors (e.g., a regular function). While the problem focuses on constructors, consider how to handle such cases gracefully (e.g., return any or throw an error).
  • Abstract classes. The instance type should be the concrete class that extends the abstract class.

Examples

Example 1:

class MyClass {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

// Usage:
const MyClassInstanceType = instanceTypeOf(MyClass);
// MyClassInstanceType should be equivalent to:
// { name: string }

Example 2:

function MyConstructor(arg: number): { value: number } {
  return { value: arg };
}

// Usage:
const MyConstructorInstanceType = instanceTypeOf(MyConstructor);
// MyConstructorInstanceType should be equivalent to:
// { value: number }

Example 3:

abstract class AbstractClass {
  abstract method(): void;
}

class ConcreteClass extends AbstractClass {
  method(): void {
    console.log("Method called");
  }
}

// Usage:
const ConcreteClassInstanceType = instanceTypeOf(ConcreteClass);
// ConcreteClassInstanceType should be equivalent to:
// { method(): void }

Constraints

  • The function must be written in TypeScript.
  • The function should be as type-safe as possible.
  • The function should not rely on any external libraries.
  • The function should be relatively performant; avoid unnecessary complexity.
  • The input constructor function can be any valid TypeScript constructor function.

Notes

  • Consider using TypeScript's type inference capabilities to simplify the implementation.
  • The InstanceType<typeof Constructor> utility type is a built-in TypeScript type that can be helpful, but the challenge is to implement the logic yourself. You are not forbidden from using it, but the goal is to understand the underlying mechanism.
  • Think about how to handle constructors that don't actually create instances (e.g., factory functions). Returning any is a reasonable approach in such cases.
  • Pay close attention to the return type of the constructor. It might be different from the instance type.
Loading editor...
typescript