返回具有额外属性的 arg 的 TypeScript 函数 (TS2322)

Posted

技术标签:

【中文标题】返回具有额外属性的 arg 的 TypeScript 函数 (TS2322)【英文标题】:TypeScript function that returns arg with extra property (TS2322) 【发布时间】:2021-07-17 02:28:06 【问题描述】:

我想实现一个函数,它接受一个具有一些已知属性和一些未知属性的对象,然后返回一个添加了一些额外属性的对象:

function addY( x, ...props) 
  return 
    x,
    y: x + 1,
    ...props,
  ;

我试过这个:

function addY<T extends  x: number >( x, ...props : T): T &  y: number  
  return 
    x,
    ...props,
    y: x + 1,
  ;

我得到的错误是:

TS2322:类型' x:数字; & 省略 & y: number; ' 不是 可分配给类型 'T & y: number; '。键入' x:数字; & 省略 & y: number; ' 不可分配给类型 'T'。 ' x:数字; & 省略 & y: number; ' 可分配给 'T' 类型的约束,但 'T' 可以用不同的实例 约束的子类型 ' x: number; '

我假设如果输入对象有一个与数字不兼容的参数y,那么返回对象将是不可能的。所以我试图通过以下方式减轻它:

function addY<T extends  x: number >( x, ...props : T): Omit<T, "y"> &  y: number  
  return 
    x,
    ...props,
    y: x + 1,
  ;

这给出了错误:

TS2322:类型' x:数字; & 省略 & y: number; ' 不是 可分配给类型 'Omit & y: number; '。键入' x: 数字; & 省略 & y: number; ' 不可分配给类型 '省略'

【问题讨论】:

去掉返回类型,看看TypeScript怎么说 @RobertoZvjerković 如果没有返回签名,它仅在y 不在props 中时才有效。如果是,y 的类型将被错误地推断为typeof props.ynumber 的交集。 【参考方案1】:

在 TypeScript 中使用扩展语法伪造对象字面量并获取类型可能很棘手。假设x 没有改变,您可以通过不提取x 并将其添加回结果来稍微简化问题,而是单独解构props

function addY<T extends  x: number >(props: T): Omit<T, 'y'> &  y: number  
  const x = props
  return 
    ...props,
    y: x + 1,
  ;

这个类型检查,如果你定义了一个函数Normalize来摆脱类型别名

type Normalize<T> = [K in keyof T]: T[K]

您可以检查返回类型是否符合预期:

const o1 = addY(x:10, z: 1)
type TestO1 = Normalize<typeof o1> // x: number, z: number, y: number

const o2 = addY(x:10, z: 1, y: 'str')
type TestO2 = Normalize<typeof o2> // x: number, z: number, y: number

当然,您也可以使用props.x 代替解构。

TypeScript playground

【讨论】:

以上是关于返回具有额外属性的 arg 的 TypeScript 函数 (TS2322)的主要内容,如果未能解决你的问题,请参考以下文章

具有额外属性的子类构造函数

具有 gradle 额外属性的自动增量版本代码

Alamofire:具有额外属性的可编码对象

具有额外配置的导航属性的模型派生类

来自具有额外属性的 JS 的淘汰赛映射

在 django 中表示具有额外属性的 manytomanyfield