TypeScript 部分函数带有泛型丢失了类型约束,

nzrxty8p  于 6个月前  发布在  TypeScript
关注(0)|答案(1)|浏览(46)

🔎 搜索词

通用
带有通用参数的部分函数会失去类型约束

🕗 版本与回归信息

  • 这会导致崩溃
  • nightly__ 和 4.x___ 版本之间发生了变化
  • 此更改发生在提交或PR中
  • 我在尝试的每个版本中都遇到了这种行为,并查阅了关于通用、失去类型约束的FAQ条目
  • 由于低于4.0的版本不支持tailargs,因此我无法在此之前的版本上进行测试

⏯ Playground链接

https://www.typescriptlang.org/play?ts=5.4.0-dev.20240107#code/PTAEFsEsDtPBDANqATgUwA4oPYBMCuAxmgFAkAuAnhmqAIIoqgC8qa8u20ilo80lANoBdMgDN80QuUhdQGeChlIAwkkQAeACqg0AD3JpouAM71GAGlABVXQaOnzKKwCUAfAAoSoUGIBcoB4AdCGKAOYmAYIhQVpWMdbCAJQsbqAuFt6gMQAW7LgMEQFaJCkA3lno5Pgo0IEx5PCQiIWRNinMaWLBIXkcrfEhjc2tSSQAvmSEXCbkEPCEOTBozBU+WJDEAQDMAAyZPvBhaH4AjLsT4pLSsnXQ+OAqOfzH2naGxmYuaNMouBqzFAwMJWe7gABGaBQbk8oGw4IAVn44qAANZoSgBdGUbBiUAo3BoRCNAJgyEoJJrHw+Ko1OrwhGCbHCADUhOJ8EuEikMjkYKeLzQpze+g+jm+v3+gOBoIe5JhHjRGKxGNx+KsDORFnZJNAZKhlKy1NptThiKZGNZOs5kxI02gs1AhkdrH5z2gxw8CEWy1AVgA5Ec0P6rOcxiQQKAAALkEwAWn0NGkCcY2BQdpmc2d5FOLD1DwFHrQXoWS2gaAsgZD5z94YzDrm3rLaAAcgX3cdWAolJBVOoPG7BVYm8tw5GTDlsPhELhQJBQCY0LR4LpU0w8uhQAB+euOwynVgj8ttx4d4tViwAJl2YyAA

💻 代码

// minimal reproduce

type Arr = readonly any[]

function partialCall<T extends Arr, U extends Arr, R>(
  f: (...args: [...T, ...U]) => R,
  ...headArgs: T
) {
  return (...tailArgs: U) => f(...headArgs, ...tailArgs)
}

const machine={
  price: 30,
  age:10
}

function numChange<T extends Record<string, number>>( obj:T, key: keyof T, delta: number){
     return obj[key]+delta
}

const test = numChange(machine , 'age', 10)

// @ts-expect-error
const test1 = numChange(machine,'a',10 ,)

const machineNumChange= partialCall(numChange, machine)

// should i see a error here ?
const te1= machineNumChange('a',20)

🙁 实际行为

我正在使用一个带有另一个泛型函数的部分函数,返回的函数会失去其参数上的类型约束。

🙂 预期行为

返回的函数应具有其参数上的类型约束。

t1rydlwq

t1rydlwq1#

这将需要对如何将通用签名的推断合并到推断上下文中进行更改。问题在于,上下文中已经存在一个针对 T 的推断候选项。 U 仅出现在该通用签名中 - 在逆变位置上。因此,也许可以从通用签名中推断出的结果可以保留下来,然后基于一些使用现有推断示例化的规则。
另一个可能起作用的例子(当外部 T 的推断不依赖于内部 T 时):

type Arr = readonly any[];

function partialCall<T extends Arr, U extends Arr, R>(
  f: (...args: [...T, ...U]) => R,
  ...headArgs: T
) {
  return (...tailArgs: U) => f(...headArgs, ...tailArgs);
}

function fn<T extends Record<string, number>>(
  delta: number,
  key: keyof T,
  obj: T,
) {
  return obj[key] + delta;
}

// actual: const result: (...tailArgs: Arr) => number
// expected: const result: <T extends Record<string, number>>(key: keyof T, obj: T) => number
const result = partialCall(fn, 10);

以及这个没有内部 T 和 U 之间任何依赖关系的例子:

type Arr = readonly any[];

function partialCall<T extends Arr, U extends Arr, R>(
  f: (...args: [...T, ...U]) => R,
  ...headArgs: T
) {
  return (...tailArgs: U) => f(...headArgs, ...tailArgs);
}

declare function fn<T extends Record<string, number>>(
  obj: T,
  delta: number,
): void;

// actual: const result: (...tailArgs: Arr) => void
// expected: const result: (delata: number) => void
const result = partialCall(fn, { a: 1 });

相关问题