在Typescript中是否可以用索引签名定义一个接口,其中索引所引用的属性的值是同一泛型的不同类型?
让我尝试解释一下:
我有一个具有以下通用签名的函数Foo:
df <- structure(list(COlA = c(1, 2),
COlB = c("list(ved = \"19\", ved_name = \"No\", vedd = \"11\")",
"list(ved = c(\"65\", \"83\", \"2\"), ved_name = c(\"At\", \"Re\", \"Rum\"), vedd = c(\"11\", \"11\", \"11\"))" )),
row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame" ))
然后是一个对象,它将由一堆类型为Foo的函数组成,但每个函数具有不同的通用参数。所以:
interface Foo<T> {(arg1: Moo<T>): T}
interface Moo<N> {nest: N}
但是我不想在接口中显式定义每个函数。我想要类似的东西:
interface Foos {
bar: Foo<number>,
baz: Foo<string>
}
const foos:Foos = {
bar: x => x.nest,
baz: y => y.nest
}
但是,当然,如果我这样做了,我会在foosTwo.bar和foosTwo.baz上丢失任何形式的实际输入-它们都只是interface FoosTwo {[K:string]: Foo<any>}
const foosTwo:FoosTwo = {
bar: x => x.nest,
baz: y => y.nest
}
。这是有道理的-编译器将如何知道我想要什么?
但是有什么方法可以告诉编译器Foo的内联类型是什么,即类似这样的东西(我意识到这是行不通的)?
Foo<any>
换句话说,是否有某种方法可以为编译器提供足够的信息,以找出bar是interface FoosTwo {[K:string]: Foo<any>}
const foosTwo:FoosTwo = {
bar<number>: x => x.nest,
baz<string>: y => y.nest
}
而baz是Foo<number>
而不需要为每个函数明确定义完整类型? / p>
非常感谢
答案 0 :(得分:0)
一个选项:
const foosTwo = {
bar: (x => x.nest) as Foo<number>,
baz: (y => y.nest) as Foo<string>
}
答案 1 :(得分:0)
根据上面@ aleksey-l的建议,我现在看到的解决方案很简单。
将其视为索引签名的问题(这就是我正在做的事情),这是错误的。诸如[K:string]或Record(string,any)之类的索引签名必然是宽松的,因为对于满足签名要求的任何内容,它们都必须相同。这就是为什么我能做的最好的事情就是interface FoosTwo {[K:string]: Foo<any>}
。
事实证明,我真正想TS要做的是推断一个强类型的界面,就像我上面介绍的手册一样:
interface Foos {
bar: Foo<number>,
baz: Foo<string>
}
执行此操作的方法是使用标识函数和泛型使TS基本上吸收一些键入信息,然后使用该信息键入最终函数。所以这个:
function createFoo<T>(func: Foo<T>):Foo<T> {
return func
}
const foosTwo = {
bar: createFoo<number>(x => x.nest),
baz: createFoo<string>( y => y.nest)
}
一个简单的标识函数,它使用泛型提供的“提示”以我想要的方式键入返回的(相同)函数。 @ alexksey-l的解决方案同样有效,尽管其表达方式与我提出的问题略有不同。他获得了答案(也让我睁开了使用泛型的某些力量的印象)。
此处是a playground,提供了完整的解决方案。