如何从函数类型中删除 key/property

How to remove a key/property from a function type

如何从以下函数类型中删除 name

type Func = {
  (): number
  name: string
}

Omit<Func, 'name'> 结果 never.

Playground link

你不能真正做到这一点,因为 name is part of the special built-in Function interface,TypeScript 中的所有可调用项都继承自它。一旦编译器发现一个类型是可调用的,它就会有一个 name(以及一个 bind 和一个 call 和一个 apply,等等)。您将无法加宽类型以删除这些键。

有关此问题的规范问题,请参阅 microsoft/TypeScript#27575。我不知道那里会发生什么,但如果你想增加它被解决的机会,你应该去那里描述你的用例并给出一个。

无论如何,您最接近这里的是 name 类型 never,这是变窄而不是变宽:

type MyFunc = {
  (): number;
  readonly name: never;
};

您仍然可以调用它:

declare const f: MyFunc;
const num = f(); // okay

虽然它一个name:

f.name; // no error here, but

name 不再被视为可用的 string 类型:

f.name.toUpperCase(); // error
// Property 'toUpperCase' does not exist on type 'never'.

如果,你说的是不同的 属性 那是 不是 built-in 到 Function,比如

type MyFuncTwo = {
  (): number;
  title: string;
  age: number;
}

然后你可以删除那些但不能使用 Omit<>,它是一个映射类型。映射类型跳过 call/construct 个签名。也有一个悬而未决的问题:microsoft/TypeScript#29261。要解决这个问题,您需要制作自己的类型映射器 re-adds 调用签名:

type MyOmit<T, K extends PropertyKey> =
  (T extends (...args: infer A) => infer R ? (...args: A) => R : unknown) & Omit<T, K>;

这适用于上面的示例:

type MyFuncThree = MyOmit<MyFuncTwo, "title">;
// type MyFuncThree = (() => number) & Pick<MyFuncTwo, "age">

但是围绕重载和泛型可能存在各种边缘情况。如果你真的想看 non-workaround 你可能想去 #29261 并给它一个并描述你的用例。


Playground link to code