You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
2.2 KiB

1 month ago
  1. type RemoveFromTuple<
  2. Tuple extends readonly unknown[],
  3. RemoveCount extends number,
  4. Index extends 1[] = []
  5. > = Index["length"] extends RemoveCount
  6. ? Tuple
  7. : Tuple extends [infer First, ...infer Rest]
  8. ? RemoveFromTuple<Rest, RemoveCount, [...Index, 1]>
  9. : Tuple;
  10. type ConcatTuples<
  11. Prefix extends readonly unknown[],
  12. Suffix extends readonly unknown[]
  13. > = [...Prefix, ...Suffix];
  14. type ExtractFunctionParams<T> = T extends (this: infer TThis, ...args: infer P extends readonly unknown[]) => infer R
  15. ? { thisArg: TThis; params: P; returnType: R }
  16. : never;
  17. type BindFunction<
  18. T extends (this: any, ...args: any[]) => any,
  19. TThis,
  20. TBoundArgs extends readonly unknown[],
  21. ReceiverBound extends boolean
  22. > = ExtractFunctionParams<T> extends {
  23. thisArg: infer OrigThis;
  24. params: infer P extends readonly unknown[];
  25. returnType: infer R;
  26. }
  27. ? ReceiverBound extends true
  28. ? (...args: RemoveFromTuple<P, Extract<TBoundArgs["length"], number>>) => R extends [OrigThis, ...infer Rest]
  29. ? [TThis, ...Rest] // Replace `this` with `thisArg`
  30. : R
  31. : <U, RemainingArgs extends RemoveFromTuple<P, Extract<TBoundArgs["length"], number>>>(
  32. thisArg: U,
  33. ...args: RemainingArgs
  34. ) => R extends [OrigThis, ...infer Rest]
  35. ? [U, ...ConcatTuples<TBoundArgs, Rest>] // Preserve bound args in return type
  36. : R
  37. : never;
  38. declare function callBind<
  39. const T extends (this: any, ...args: any[]) => any,
  40. Extracted extends ExtractFunctionParams<T>,
  41. const TBoundArgs extends Partial<Extracted["params"]> & readonly unknown[],
  42. const TThis extends Extracted["thisArg"]
  43. >(
  44. args: [fn: T, thisArg: TThis, ...boundArgs: TBoundArgs]
  45. ): BindFunction<T, TThis, TBoundArgs, true>;
  46. declare function callBind<
  47. const T extends (this: any, ...args: any[]) => any,
  48. Extracted extends ExtractFunctionParams<T>,
  49. const TBoundArgs extends Partial<Extracted["params"]> & readonly unknown[]
  50. >(
  51. args: [fn: T, ...boundArgs: TBoundArgs]
  52. ): BindFunction<T, Extracted["thisArg"], TBoundArgs, false>;
  53. declare function callBind<const TArgs extends readonly unknown[]>(
  54. args: [fn: Exclude<TArgs[0], Function>, ...rest: TArgs]
  55. ): never;
  56. // export as namespace callBind;
  57. export = callBind;