You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何复用底层库类型,为链式调用包装类推断方法签名?

Absolutely! You can absolutely reuse and extend the type definitions from your underlying library to get full type inference for your chainable wrapper. Here's how to modify your implementation to make TypeScript aware of all the library methods and their signatures:

Step 1: Capture the Library's Type Definition

First, we'll extract the full type of your library so we can reference it throughout our chainable class:

import lib from 'lib';

// Get the complete type definition of the library
type Lib = typeof lib;
Step 2: Define a Chainable Method Type Mapping

We'll create a generic type that transforms each method in the library into a chainable version. This type will automatically adapt to the library's method signatures, removing the need to manually pass the current value as the first argument:

// Transform library methods into chainable equivalents
type ChainableMethods<T> = {
  [MethodName in keyof Lib]: 
    Lib[MethodName] extends (input: T, ...args: infer ExtraArgs) => infer ReturnValue
      ? (...args: ExtraArgs) => Chainable<ReturnValue>
      : never;
};

What this does:

  • For every method in the library, we check if it accepts the current chainable value type (T) as its first argument
  • If it does, we create a new method signature that accepts only the remaining arguments of the original method
  • The new method returns an updated Chainable instance with the return type of the original method as its new value type
Step 3: Build the Generic Chainable Class

We'll turn your original Chainable class into a generic class that implements our mapped ChainableMethods<T> interface. This tells TypeScript about all the dynamically added methods:

class Chainable<T> implements ChainableMethods<T> {
  public value: T;

  constructor(value: T) {
    this.value = value;
  }
}
Step 4: Keep Dynamic Method Assignment (With Type Safety)

We'll retain your original dynamic method injection logic, but add type assertions to keep TypeScript happy:

// Dynamically attach all library methods to the Chainable prototype
const methods = Object.keys(lib) as Array<keyof Lib>;
for (const method of methods) {
  Chainable.prototype[method] = function(this: Chainable<any>, ...args: any[]) {
    this.value = Reflect.apply(lib[method], null, [this.value, ...args]);
    return this;
  };
}

export default Chainable;
Step 5: Enjoy Full Type Inference

Now when you use your Chainable class, TypeScript will automatically:

  • Validate arguments for every library method
  • Infer the correct type of value after each method call
  • Prevent calls to methods that don't accept the current value type

Example usage:

// TypeScript will enforce lib.one's signature, infer the next value type, and so on
const result = new Chainable('abc')
  .one()
  .two(/* If lib.two requires extra args, TypeScript will enforce them here */)
  .three()
  .value; // Type is automatically set to the return type of lib.three

Bonus: Handling Method Overloads

This implementation works seamlessly with library methods that have overloads—TypeScript will recognize all valid overload signatures for each chainable method.

内容的提问来源于stack exchange,提问作者i_like_robots

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:18:43