Typescript 如何混合接口的动态([key: type]: type)和静态类型

Del*_*ium 5 interface typescript reactjs

主要问题

不太确定这是否可行,但由于我讨厌 Typescript 并且它使我的编码变得困难,所以我想我会问一下以确保确定。

interface ISomeInterface {
  handler: () => {}
  [key: string]: string
}
Run Code Online (Sandbox Code Playgroud)

问题显然是,它handler是一个() => {}而不是字符串,所以打字稿会抛出错误。有可能以某种方式使这项工作有效吗?

附录:

在主题中,该接口应该由 a 使用React.Context,并且由于 需要默认值React.createContext(/* requires default here */),所以我需要给它一个与该接口匹配的对象。当我尝试传递对象文字时:

React.createContext({handler: () => {throw new Error('using default context')}})
Run Code Online (Sandbox Code Playgroud)

Typescript 正在引起骚动,它说{handler: () => never} cannot be assigned to {handler: () => {}}有什么方法可以让这个界面变得合理吗?我尝试使接口实现() => any,仍然不起作用,它需要显式never

编辑#1:

所以我做了一些改变,即:

interface IFormContext {
  $handleChange: (key?, val?) => void
  $registerField: (key?) => void
  [key: string]: { value: string } | ((key?, val?) => void)
}
Run Code Online (Sandbox Code Playgroud)

但是现在,当我尝试访问这样的字段时:const {[key]: { value }} = props这基本上是使用动态键进行解构,我收到以下错误:

Property 'value' does not exist on type '{ value: string; } | ((key?: any, val?: any) => void)'.ts(2339)

小智 6

不幸的是,您的命名属性必须与索引签名匹配。在这种情况下,由于至少有一个属性是函数,因此您可以使用:

[key: string]: string | Function;

或者

[key: string]: any;

两者都应该有效。

对于您的附录,() => {}意味着一个没有参数的函数返回一个空对象,而该函数() => {throw new Error('using default context')}不返回任何内容,因此出现错误。类型和实际函数实现中使用的大括号有点混乱。

具有类型的函数() => {}实际上类似于() => {return {}}or () => ({})

对于不返回任何内容的函数,您可以使用nevervoid,但如果您的处理程序可能返回某些内容,您可以使用类似 的内容handler: () => void | boolean,用它可能返回的类型替换 boolean 。