如何键入一个可以同时具有几个声明的可选属性的对象,例如:
{
hello?: string,
moo?: boolean
}
以及自定义属性(必须是函数),例如:
[custom: string]: (v?: any) => boolean
这是我希望看到的,例如:
const myBasic: Example = {moo: false}
// -> ✅ Valid! Using known keys
const myValid: Example = {hello: 'world', customYo: () => true}
// -> ✅ Valid! "customYo" is a function returning a bool. Good job!
const myInvalid: Example = {hello: 'world', customYo: 'yo!'}
// -> ☠️ Invalid! "customYo" must be a function returning a boolean
尝试向具有已知键的接口(例如hello?: string, moo?: boolean
)添加索引签名要求所有键都是索引签名类型的子集(在本例中,函数返回boolean
),这显然会失败。
4条答案
按热度按时间x3naxklr1#
业主接受的问题(到目前为止)是不正确的。
以下是您的操作方法:
您需要使索引签名成为接口中可以包含的所有类型的联合类型:
请注意,为了提高可读性,我已经将函数类型提取到了一个单独的接口中。
含义:
这意味着TS很好地支持显式定义的属性:
然而,现在需要使用类型保护来检查索引签名中的所有属性,这会增加一点运行时开销:
另一方面:运行时开销是必要的,因为
test
可能是这样访问的:x0fgdtte2#
根据设计https://basarat.gitbooks.io/typescript/docs/types/index-signatures.html,这是不可能的
一旦你有了一个字符串索引签名,所有的显式成员也必须符合这个索引签名。这是为了提供安全性,以便任何字符串访问都给出相同的结果。
解决这个问题的唯一方法是利用每个接口可以有两个单独的索引签名,一个用于
string
,另一个用于number
在本例中,
hello
和moo
使字符串索引不可用,但您可以劫持自定义方法的数字索引这是可行的,但几乎不是一个可接受的接口,因为这将导致不直观的函数,您将不得不通过数组符号来调用它们
还有一点需要注意,从数字索引器返回的类型必须是从字符串索引器返回的类型的子类型,这是因为当使用数字进行索引时,javascript会在索引到对象之前将数字转换为字符串
在这种情况下,您没有显式的字符串索引器,因此字符串索引类型是数字索引器类型可以遵循的缺省值
any
重要提示这只是为了科学,我不建议将其作为真实的生活中的方法!
mjqavswn3#
迟到了,但是你可以使用泛型,并使一些条件式工作
这需要注意以下几点:
rt4zxlrg4#
实现@NicBright的答案的一个非常简单的方法是使用“高阶类型”,它可以用任何你想要的索引签名来扩展你已经定义的类型,例如:
这种方法的好处是可以将高阶类型应用于其他结构(WithCustomFunctions的可重用性)。
坏消息是他的解决方案的所有含义仍然适用。