我正在尝试在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
}
非常感谢
答案 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
重叠的任何键