Typescript:如何使类型接受键与泛型匹配但所有值都是值参数的映射函数的对象

Typescript:如何使类型接受键与泛型匹配但所有值都是值参数的映射函数的对象,typescript,types,typescript-typings,type-inference,typescript-generics,Typescript,Types,Typescript Typings,Type Inference,Typescript Generics,我想实现这样的类型:“我的所有键递归地与typeT相同,但我的所有值都是接受这样的键值并映射它的函数 我尝试了下面的代码,但它没有推断出指定函数的返回类型,递归性是错误的 export type ObjectButAllKeyIsValueFn<T> = { [K in keyof T]?: ObjectButAllKeyIsValueFn<T[K]> | (<R>(value: T[K]) => R) } interface User {

我想实现这样的类型:“我的所有键递归地与typeT相同,但我的所有值都是接受这样的键值并映射它的函数

我尝试了下面的代码,但它没有推断出指定函数的返回类型,递归性是错误的

export type ObjectButAllKeyIsValueFn<T> = {
    [K in keyof T]?: ObjectButAllKeyIsValueFn<T[K]> | (<R>(value: T[K]) => R)
}


interface User {
    name: string,
    surname: string,
    address: {
        city: string,
        country: string,
        street: string
    }
}

const z: ObjectButAllKeyIsValueFn<User> = {
    name: value => `Hello ${value}`,
    address: {
        city: city => 1
    }
};

导出类型ObjectButAllKeyIsValueFn={
[K in keyof T]?:ObjectButAllKeyIsValueFn |((值:T[K])=>R)
}
界面用户{
名称:string,
姓:弦,
地址:{
城市:字符串,
国家:字符串,
街道:字符串
}
}
常量z:ObjectButalKeyIsValueFn={
名称:value=>`Hello${value}`,
地址:{
城市:城市=>1
}
};
更新: 我想实现这样的递归,所以我必须正确地将StupdPattern映射到Pattern

type StupidPattern<T> = {
    [K in keyof T]: StupidPattern<T[K]> | ((value: T[K]) => unknown)
}

type Pattern<T> = {
    [K in keyof T]: (value: T[K]) => unknown
}

type Result<T, P = Pattern<T>> = {
    [K in keyof P]: K extends keyof T
        ? P[K] extends (value: T[K]) => infer R
            ? R
            : never
        : never
}

declare function map <T> (pattern: Pattern<T>): (target: T) => Result<T, Pattern<T>>
declare function map <T> (pattern: Pattern<T>, target: T): Result<T, Pattern<T>>;

类型StupdPattern={
[K in keyof T]:StupdPattern |((值:T[K])=>未知)
}
类型模式={
[K in keyof T]:(值:T[K])=>未知
}
类型结果={
[K in keyof P]:K扩展keyof T
?P[K]扩展(值:T[K])=>推断R
R
:从不
:从不
}
声明函数映射(模式:模式):(目标:T)=>结果
声明函数映射(模式:模式,目标:T):结果;
类型
((值:T[K])=>R)
不是您要查找的;本质上,泛型
R
是错误的方式。它意味着“一个函数,其输入类型为
T[K]
,其输出为调用方指定的任何类型
R
。这实际上不可能安全地实现。大概你的意思是函数的实现者应该能够指定
R
,但是在TypeScript中没有干净的方法来表示泛型。。。您可能会将
R
作为
object的另一个通用参数,但所有键都是valuefn
,但是您需要为
T
的每个键设置一个
R
。让我们回顾一下,从另一个角度来看:

我们将
ObjectButAllKeyIsValueFun
定义为以下类型如何:

export type ObjectButAllKeyIsValueFn<T> = {
  [K in keyof T]?: ObjectButAllKeyIsValueFn<T[K]> | ((value: T[K]) => unknown)
}
下面是如何调用
asObjUser()

它可以工作并跟踪特定类型的
z
。它还捕获如下错误:

const oops = asObjUser({
  name: 123, // error!
  // number is not assignable to string | ((value: string) => unknown) | undefined
});
所以,希望这足以让你取得进步。祝你好运


((值:T[K])=>T[K])
如果我理解您的意思,返回值需要与参数相同correctly@Marv不,它不是,您可以将值映射到任何类型,但我想在参数中保留该类型,并在生成的对象上具有正确的类型。我无法了解如何正确使用此类curried函数和获取类型。实际上,我的代码在js上正常运行,但无法在typescript中进行注释和重写。我想要实现的目标是一个函数,它允许通过值的结构声明映射来映射值。因此,在我的模型中,我有一些模式对象,它们的键与我想要映射的目标值完全相同,但值是接受目标“对象”值并映射它们的函数。还有一个问题是,我在这里使用递归映射,编写递归类型非常困难:PI并不真正理解这个注释,我也没有在您编辑的代码中看到这个问题。你能确定这是一个能清楚地表明你所面临的问题的例子吗?祝你好运
const z = asObjUser({
  name: value => `Hello ${value}`,
  address: {
    city: city => 1
  }
});

/* const z: {
    name: (value: string) => string;
    address: {
        city: (city: string) => number;
    };
} */

console.log(z.name("Fred")); // Hello Fred
const oops = asObjUser({
  name: 123, // error!
  // number is not assignable to string | ((value: string) => unknown) | undefined
});