Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 具有自引用泛型类型的记录_Typescript_Typescript Generics - Fatal编程技术网

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"