首页 > 解决方案 > 打字稿:安全地从对象中删除属性

问题描述

我想编写一个打字稿函数,它接受一个包含参数的对象foo并输出没有参数的相同对象foo。我想以类型安全的方式完成这一切。看起来很简单,但我磕磕绊绊。这是我到目前为止的代码:

interface FooProp {
    foo: string;
}
type WithFooProp<P extends object> = P extends FooProp ? P : never;
type WithoutFooProp<P extends object> = P extends FooProp ? never: P;

function withoutFooProp<P extends object>(input: WithFooProp<P>): WithoutFooProp<P> {
    // How do I get rid of these any's
    const {foo, ...withoutFoo} = input as any;
    return withoutFoo as any;
}

这不是很好,因为我使用any了一堆。我有点希望代码可以在没有 的情况下按原样工作any,但是 TS 抱怨这input不是对象并且不能被解构。我该如何改进这种方法?

另外,当我使用这个函数时,TS 强制我显式地提供泛型类型。我希望它会隐式推断类型。有什么方法可以编写函数来隐式获取参数。

// Compiles - but I have to specify the props explicitly
withoutFooProp<{foo: string, bar: string}>({
    foo: 'hi',
    bar: 'hi',
});

// This doesn't compile - I wish it did!  How can I make it?
withoutFooProp({
    foo: 'hi',
    bar: 'hi',
});

提前致谢!

标签: typescript

解决方案


您可以让参数类型为 simple P,其中P限制为包含foo属性,以便类型推断将起作用:它只会设置P为参数类型。然后使用PickandExclude生成包含Pexcept的所有属性的输出对象的类型foo

interface FooProp {
    foo: string;
}
type WithoutFooProp<P> = Pick<P, Exclude<keyof P, "foo">>;

function withoutFooProp<P extends FooProp>(input: P): WithoutFooProp<P> {
    const {foo, ...withoutFoo} = input as any;
    return withoutFoo;
}

any除非/直到实施此建议,否则您将无法摆脱。我不会担心的。

withoutFooProp函数应该适用于任何具体的输入类型,并为您提供具体的输出类型。如果您withoutFooProp在泛型类型的对象上使用,那么您可能会遇到问题,因为 TypeScript 对Pickand的推理能力有限Exclude,您可能希望使用交集来代替(即使这样做在技术上是不合理的),如this answer in React 高阶组件的上下文。


推荐阅读