如何在 TypeScript 中声明仅包含对象而不包含函数的类型

Posted

技术标签:

【中文标题】如何在 TypeScript 中声明仅包含对象而不包含函数的类型【英文标题】:How to declare a type in TypeScript that only includes objects and not functions 【发布时间】:2019-03-12 13:18:18 【问题描述】:

是否可以在 TypeScript 中以某种方式定义一个类型,使其只包含对象而不包含函数?

例子:

type T =  [name: string]: any  // How to modify this to only accepts objects???

const t: T = () =>  // <- This should not work after modification

感谢您的帮助。

【问题讨论】:

我完全理解你的问题,但在这里只是为了扮演魔鬼的拥护者,如果有人传入一个函数,如果它包含你期望它具有的所有属性会有什么问题? 这是关于重载具有 arity 1 的函数:对象参数的第一个签名,函数参数的第二个签名。在我的代码中,编译器总是采用第一个签名(对于对象和函数),这导致了非预期的类型推断。在我的特殊情况下,解决方案是更改签名声明的顺序。希望我的意思很清楚。意味着:我的问题已经解决了,但是我仍然对上述问题的答案感兴趣......顺便说一句:Exclude 之类的东西似乎也不起作用...... 这是有道理的。据我所知,它需要运行时检查来区分函数和普通对象,因为在 javascript 中,函数 is 是一个对象。我相信Exclude 不起作用,因为在执行它不扩展Function 的断言之前,赋值将函数的类型扩大到T 【参考方案1】:

没有完美的方式来引用像“不是函数的对象”这样的类型,因为这需要真正的subtraction types,而这在 TypeScript 中不存在(至少从 3.1 开始)。

一个足够简单的解决方法是查看Function interface 并描述绝对不是 Function 的东西,但它会匹配您可能运行的大多数非功能对象进入。示例:

type NotAFunction =  [k: string]: unknown  & ( bind?: never  |  call?: never );

这意味着“一个带有一些未指定键的对象,它要么缺少bind 属性,要么缺少call 属性”。让我们看看它的表现:

const okayObject: NotAFunction =  a: "hey", b: 2, c: true ;
const notOkayObject: NotAFunction = () => ; // error, call is not undefined

很好。

这是一种变通方法而不是简单的解决方案的原因是某些非函数可能同时具有callbind 属性,这只是巧合,您会得到一个不受欢迎的错误:

const surprisinglyNotOkay: NotAFunction =  
  publication: "magazine", 
  bind: "staples",
  call: "867-5309",
  fax: null
; // error, call is not undefined

如果您确实需要支持此类对象,您可以将NotAFunction 更改为更复杂并排除更少的非函数,但定义可能总会出错。这取决于你how far you want to go。

希望对您有所帮助。祝你好运!

【讨论】:

LOL 链接很棒

以上是关于如何在 TypeScript 中声明仅包含对象而不包含函数的类型的主要内容,如果未能解决你的问题,请参考以下文章

如何将 package.json 导入 Typescript 文件而不将其包含在编译输出中?

TypeScript教程# 13:接口

如何键入 Typescript 数组以仅接受一组特定的值?

Typescript - 如何声明具有已知属性的匿名对象?

TypeScript 中关联对象数组的接口

Typescript:如何声明一种值等于对象键的数组类型?