How do I remove name
from the following function type:
type Func = {
(): number
name: string
}
Omit<Func, 'name'>
result in never
.
You can't really do this because name
is part of the special built-in Function
interface, which all callables in TypeScript inherit from. As soon as the compiler sees that a type is callable, it will have a name
(and a bind
and a call
and an apply
, etc). You won't be able to widen the type to remove those keys.
See microsoft/TypeScript#27575 for the canonical issue about this. I don't know that anything will happen there, but that's where you should go to describe your use case and give a 👍 if you want to increase the chance of it being addressed.
Anyway, the closest you will be able to get here is to have name
be of type never
, which is a narrowing and not a widening:
type MyFunc = {
(): number;
readonly name: never;
};
You can still call it:
declare const f: MyFunc;
const num = f(); // okay
And while it does have a name
:
f.name; // no error here, but
That name
is no longer seen as a usable string
type:
f.name.toUpperCase(); // error
// Property 'toUpperCase' does not exist on type 'never'.
If, you were talking about a different property that's not built-in to Function
, like
type MyFuncTwo = {
(): number;
title: string;
age: number;
}
then you can remove those but not with Omit<>
, which is a mapped type. Mapped types skip call/construct signatures. There's an open issue for that too: microsoft/TypeScript#29261. To work around that, you'd need to make your own type mapper that re-adds the call signature:
type MyOmit<T, K extends PropertyKey> =
(T extends (...args: infer A) => infer R ? (...args: A) => R : unknown) & Omit<T, K>;
That works for the example above:
type MyFuncThree = MyOmit<MyFuncTwo, "title">;
// type MyFuncThree = (() => number) & Pick<MyFuncTwo, "age">
but there are all sorts of edge cases around overloads and maybe generics. If you really want to see a non-workaround you might want to go to #29261 and give it a 👍 and describe your use case.