Typescript 具有自引用泛型类型的记录
我有一个函数如下所示:Typescript 具有自引用泛型类型的记录,typescript,typescript-generics,Typescript,Typescript Generics,我有一个函数如下所示: function create<A extends Record<string, (r:{[k in keyof A]: ReturnType<A[k]>}) => any>> //the Record Value is a function that takes the keys and return values of A as it's argument (options:A) : any { ...
function create<A extends
Record<string, (r:{[k in keyof A]: ReturnType<A[k]>}) => any>> //the Record Value is a function that takes the keys and return values of A as it's argument
(options:A) : any {
...
}
在同一记录中键入其他值时,有没有办法做到这一点?如果将
选项定义为记录
,这意味着每个字符串
都是选项
的有效键。因此,您将无法区分有效密钥和无效密钥
一种解决方案是使用泛型来描述映射器的键。这并不完美——我们知道r.test
存在并且是一个函数,但是我们不知道返回类型,也不知道它实际上没有使用参数,所以我们必须传递r
来调用它
type OptionsObject<Keys extends PropertyKey> = {
[K in Keys]: (r: OptionsObject<Keys>) => any;
}
function create<Keys extends PropertyKey>
(options: OptionsObject<Keys>) : any {
}
create({
test: () => "TEST",
lower: (r) => r.test(r).toLowerCase()
})
编辑:我想我误解了这一点“记录值是一个以a的键和返回值作为参数的函数”,而您想要的是(r:Map)=>
,而不是(r:optionObject)=>
,我不确定我是否理解了这个想法:
type OptionsObject<Map> = {
[K in keyof Map]: ((K?: any) => Map[K]);
}
function create<Map>(options: any): OptionsObject<Map> {
return options;
}
const opt = {
test: () => "TeSt",
lower: (r: any) => r.test(r).toLowerCase(),
upper: (r: any) => r.test(r).toUpperCase()
}
const a = create<typeof opt>(opt)
console.log('a.test()', a.test()) // "a.test()", "TeSt"
console.log('a.lower(a)', a.lower(a)) // "a.lower(a)", "test"
console.log('a.upper(a)', a.upper(a)) // "a.upper(a)", "TEST"
类型选项对象={
[K in keyof Map]:((K?:any)=>Map[K]);
}
函数创建(选项:任意):选项对象{
返回选项;
}
常数opt={
测试:()=>“测试”,
lower:(r:any)=>r.test(r).toLowerCase(),
上限:(r:any)=>r.test(r).toUpperCase()
}
常数a=创建(opt)
console.log('a.test()',a.test())/“a.test()”,“test”
console.log('a.lower(a)'、a.lower(a))/“a.lower(a)”、“test”
console.log('a.upper(a)'、a.upper(a))/“a.upper(a)”、“TEST”
这没有什么意义,因为在您的示例中,属性a
的类型为string
,因此此对象的类型不能是Record
的子类型,其中值类型是函数。@kaya3-我稍微细化了这个问题。请让我知道这是否更符合定义您的记录
类型的键是每个字符串
。因此,您不能真正告诉它test
是一个有效的键,但foo
不是。可以键入此函数,但需要另一种方法。我将写一个答案。这非常接近(r:Map)=>),但正如您所指出的,当您包含参数时,类型变得未知
type OptionsObject<Map> = {
[K in keyof Map]: (r: OptionsObject<Map>) => Map[K];
}
function create<Map extends {}>
(options: OptionsObject<Map>) : any {
}
create({
test: () => "TEST",
lower: (r) => r.test(r).toLowerCase()
})
type OptionsObject<Map> = {
[K in keyof Map]: ((K?: any) => Map[K]);
}
function create<Map>(options: any): OptionsObject<Map> {
return options;
}
const opt = {
test: () => "TeSt",
lower: (r: any) => r.test(r).toLowerCase(),
upper: (r: any) => r.test(r).toUpperCase()
}
const a = create<typeof opt>(opt)
console.log('a.test()', a.test()) // "a.test()", "TeSt"
console.log('a.lower(a)', a.lower(a)) // "a.lower(a)", "test"
console.log('a.upper(a)', a.upper(a)) // "a.upper(a)", "TEST"