返回没有某些键的对象(动态,类型安全)

时间:2019-03-06 12:49:00

标签: typescript

我正在尝试在TypeScript中实现“除外”方法。 目的将是这样的:

const obj = { a: true, b: 1, c: 'test', d: false }
const objExcept = except(obj, 'b', 'd')

我的问题不是实际的键排除,而是 typesafe 返回值。 理想情况下,访问objExcept.b应该会给我一个错误,导致返回值为:

objExcept: { a: boolean, c: string } = { a: true, c: 'test' }`

这是我目前的实现方式

export function except<
  T extends Dictionary,
  K extends any[],
  R extends Pick<T, Exclude<keyof T, K[number]>>
> (value: T, ...exceptions: K): R {
  const copy: Record<string: any> = {}
  for (const key in value) {
    if (!value.hasOwnProperty(key) || exceptions.includes(key)) continue

    copy[key] = value[key]
  }

  return copy as R
}

非常感谢

1 个答案:

答案 0 :(得分:2)

您非常接近,您只需要让编译器来推断K的文字类型。最好的方法是将K中的项目限制为keyof T。这还将检查属性键是否是目标对象的一部分。

export function except<
  T extends Record<string, any>,
  K extends Array<keyof T>,
  R extends Pick<T, Exclude<keyof T, K[number]>>
> (value: T, ...exceptions: K): R {
  const copy: Record<string, any> = {}
  for (const key in value) {
    if (!value.hasOwnProperty(key) || exceptions.includes(key)) continue

    copy[key] = value[key]
  }

  return copy as R
}

const obj = { a: true, b: 1, c: 'test', d: false }
const objExcept = except(obj, 'b', 'd')
objExcept.a
objExcept.b //err

如果您想允许任何键,而不必只是T的已知键,则也可以使用K extends Array<PropertyKey>,这将允许任何键,但排除与T重叠的任何键