javascript - 强类型对象中的 TypeScript 循环约束

标签 javascript typescript object types

我已经声明了一个像这样的对象:

const example = {
  morning: (name) => `Good morning ${name}!`,
  evening: (name) => `Good evening ${name}!`
}

在其原始形式中,该对象具有强类型键(我可以使用点表示法访问它们),但值可以是任何值。这就是为什么我决定引入类型签名:

const example: {
  [K: string]: (name: string) => string;
} = {
  morning: (name) => `Good morning ${name}!`,
  evening: (name) => `Good evening ${name}!`
}

现在我的对象值是强类型的,但键不是,我可以尝试使用点表示法访问任何键,而无需 TypeScript 提示(例如,我可以编写 console.log(example.doesntexist) ,而且我也不会获得对象键的编辑器自动完成功能)。所以我尝试了这个:

const example: {
  [K in keyof typeof example]: (name: string) => string;
} = {
  morning: (name) => `Good morning ${name}!`,
  evening: (name) => `Good evening ${name}!`
}

现在我收到循环约束错误(类型参数“K”具有循环约束并且“example”在其自己的类型注释中直接或间接引用 )。我知道我可以做这样的事情

const example: {
  [K in 'morning' | 'evening']: (name: string) => string;
} = {
  morning: (name) => `Good morning ${name}!`,
  evening: (name) => `Good evening ${name}!`
}

但这是多余的(我讨厌冗余/代码重复)。有办法做我想做的事吗?

最佳答案

如果没有一些额外的代码,就无法做到这一点。

在这种情况下,我通常会写一个 constrained通用identity function辅助函数。这与您尝试编写的循环注释非常相似:

const asExample = <K extends PropertyKey>(
  x: { [P in K]: (name: string) => string }
) => x;

此函数仅接受类型为键 K 和值 (name: string) => string) 的输入,对于某些类似键的 K 编译器推断,并返回输入。由于该函数在 K 中是通用的,因此编译器将跟踪 K,而不是扩展到诸如 string 之类的内容。

让我们测试一下:

const example = asExample({
    morning: name => `Good morning ${name}!`,
    evening: name => `Good evening ${name}!`
})

example.morning("Alice") // okay
example.day // error! 
// ---> ~~~
// Property 'day' does not exist on type
// '{ morning: (name: string) => string; evening: (name: string) => string; }'

您可以看到 example 已知在 morningevening 键处具有属性,但在 day 键。

如果您尝试在错误的输入上调用 asExample(),您将得到您想要的错误:

const badExample = asExample({
    afternoon: name => `Good afternoon ${name}!`.length, // error!
    // --------------> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // number is not assignable to string
    night: "Good night everyone!" // error!
//  ~~~~~ <-- string is not assignable to (name: string) => string
})

Playground link to code

关于javascript - 强类型对象中的 TypeScript 循环约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67761901/

相关文章:

angular - 适用于(单击)的函数不适用于 ngOnInit()

angular - 将 Moment 与 Angular 库 13 一起使用会导致错误

Java 类对象哈希更改无需更改源代码

使用 VarArgs 的 Java 对象构造函数

javascript - 如何从获取值中查找数组中的状态缩写

javascript - 使用查询的水平图像滚动

javascript - 我正在尝试将一个元素从 <select> 列表移至顶部,但我的代码似乎不起作用

javascript - typescript 对象解构结果为 "Property assignment expected."

javascript - 如何在正确的上下文中将函数传递给单击处理程序?

javascript - Chrome 扩展连接脚本 - 引用资源