Matthieu Riegler Asked: 2024-07-26 23:59:30 +0800 CST2024-07-26 23:59:30 +0800 CST 2024-07-26 23:59:30 +0800 CST 从可调用类型中删除“length”属性 772 假设我有以下类型: export type Foo<T> = (() => T) 是否可以删除该length属性但保持其可调用? 此外,使用Omit,Omit<(() => T), 'length'>会阻止其被调用。 typescript 1 个回答 Voted Best Answer jcalz 2024-07-27T03:08:43+08:002024-07-27T03:08:43+08:00 你实际上不能这样做。TypeScript 中的所有可调用对象都从接口继承,该Function接口在TypeScript es5.d.ts 库中定义为具有数字length属性。你执行的任何导致可调用类型的操作都将具有该length属性。 改变这种情况的唯一方法是本地分叉 es5.d.ts 并将其删除,但这可能会破坏很多东西并且难以维护。可能“正确”的方法是制定自定义 linter 规则,以便使用函数会length警告您这可能是一个错误。然而,在 TypeScript 本身中,您没有太多选择。 您无法将函数扩展为某种类型length,同时仍可调用,但您可以将函数缩小length为某种奇怪/不可用的类型。标准方法是将其缩小为通用子类型,因此您始终可以将其缩小为通用子never类型: type Foo<T> = (() => T) & { length: never }; declare const f: Foo<string>; f().length.toFixed(); // okay f.length.toFixed(); // error 但这不会阻止你检查f.length真实性,因为即使never在那里也是允许的。当涉及到真实性检查时,TypeScript 很少抱怨;事实上,我发现的唯一问题是当你检查一个函数但没有调用它时。所以我们可以做一些疯狂的事情,告诉 TypeScript 该length属性既是某个函数number 又是某个函数: type Foo<T> = (() => T) & { length(x: never): never }; declare const f: Foo<string>; f().length.toFixed(); // okay f.length.toFixed(); // error if (f.length) { // error but for a crazy reason console.log(1) } 但这真的是一个卑鄙的谎言;错误表明你的意图是调用 f.length,而且你确实可以这样做(尽管我通过提供一个never参数让它变得更加困难): f.length(null!) // no error, what? 所以我想说这并不是 TypeScript 能够帮你做好的事情。 游乐场链接到代码
你实际上不能这样做。TypeScript 中的所有可调用对象都从接口继承,该
Function
接口在TypeScript es5.d.ts 库中定义为具有数字length
属性。你执行的任何导致可调用类型的操作都将具有该length
属性。改变这种情况的唯一方法是本地分叉 es5.d.ts 并将其删除,但这可能会破坏很多东西并且难以维护。可能“正确”的方法是制定自定义 linter 规则,以便使用函数会
length
警告您这可能是一个错误。然而,在 TypeScript 本身中,您没有太多选择。您无法将函数扩展为某种类型
length
,同时仍可调用,但您可以将函数缩小length
为某种奇怪/不可用的类型。标准方法是将其缩小为通用子类型,因此您始终可以将其缩小为通用子never
类型:但这不会阻止你检查
f.length
真实性,因为即使never
在那里也是允许的。当涉及到真实性检查时,TypeScript 很少抱怨;事实上,我发现的唯一问题是当你检查一个函数但没有调用它时。所以我们可以做一些疯狂的事情,告诉 TypeScript 该length
属性既是某个函数number
又是某个函数:但这真的是一个卑鄙的谎言;错误表明你的意图是调用
f.length
,而且你确实可以这样做(尽管我通过提供一个never
参数让它变得更加困难):所以我想说这并不是 TypeScript 能够帮你做好的事情。
游乐场链接到代码