Typescript 函数不';t嵌套keyof的返回值

Typescript 函数不';t嵌套keyof的返回值,typescript,Typescript,我试图从一个模型级别返回值。第一级工作得很好,因为返回值的类型是T[K],这意味着['Login'、'Password'、'Address']返回我想要的内容。但当我改变 getProperty(auth,x=>x.Address) 到 getProperty(auth,x=>x.Address.Address2)。 我知道'Address2'属性不直接在T类型下。 我不知道什么类型的更改“T[K]”也适用于ie.Address2属性。 你能帮我吗 编辑:what's wordgetProper

我试图从一个模型级别返回值。第一级工作得很好,因为返回值的类型是T[K],这意味着['Login'、'Password'、'Address']返回我想要的内容。但当我改变
getProperty(auth,x=>x.Address)
getProperty(auth,x=>x.Address.Address2)。
我知道'Address2'属性不直接在T类型下。
我不知道什么类型的更改“T[K]”也适用于ie.Address2属性。
你能帮我吗

编辑:what's word
getProperty(auth,x=>x.Address.Address2.State)工作

export interface Auth {
  Login: string;
  Password: string;
  Address: {
      Address2: {
        State: string;
      }
  }
}

let auth: Auth = {
    Login: 'login',
    Password: 'password',
    Address: {
        Address2:{
            State: 'some state'
        }
    }
  };


function getProperty<T, K extends keyof T>(obj: T, fn: (m: T) => T[K]) {
    console.log(fn(obj));
}

getProperty(auth, x => x.Address.Address2);
导出接口身份验证{
登录:字符串;
密码:字符串;
地址:{
地址2:{
状态:字符串;
}
}
}
让auth:auth={
登录:'登录',
密码:“Password”,
地址:{
地址2:{
州:“某个州”
}
}
};
函数getProperty(obj:T,fn:(m:T)=>T[K]){
控制台日志(fn(obj));
}
getProperty(auth,x=>x.Address.Address2);
函数getProperty(obj:T,fn:(m:T)=>B):B{
返回fn(obj);
}
const testType=getProperty(auth,x=>x.Address.Address2);//一串
希望这能有所帮助,据我所知,没有办法输入deep,函数返回一个由T的索引产生的类型,因为没有办法表示这个“deep”。也就是说,你可以表达T[K],但只能表达到1的深度。另一种可以完全表达深键访问的语法是这样的

interface IGetProperty<Original, Access> {
    value: Access,
    pick: <K extends keyof Access>(key: K) => IGetProperty<Original, Access[K]>
}

const getProperty = <Original, Access = Original>(obj: Original): IGetProperty<Original, Access> => {
   return {
       value: obj as any,
       pick: (key) => getProperty((obj as any)[key as any]) as any
   }
}

const testType = getProperty(auth).pick("Address").pick("Address2").pick("State").value // string.
const testType = getProperty(auth).pick("Address").pick("Invalid Key").pick("State").value // Error.
接口IGetProperty{
值:访问,
拾取:(键:K)=>IGetProperty
}
常量getProperty=(对象:原始):IGetProperty=>{
返回{
值:obj(如有),
拾取:(键)=>getProperty((对象为任意)[键为任意])为任意
}
}
const testType=getProperty(auth).pick(“地址”).pick(“地址2”).pick(“状态”).value//string。
const testType=getProperty(auth).pick(“地址”).pick(“无效键”).pick(“状态”).value//错误。

编辑:在typescript中,即使您可以键入一个函数来返回T[K],它不会“强制”函数返回从“T”索引的某个值,因为如果T[K]是字符串,那么您可以返回任何不是来自“T”的字符串,例如“hello”,它仍然会进行类型检查,发生这种情况是因为Typescript在结构上而不是名义上键入内容。如果[K]的类型是全局唯一的,那么这种行为是可能的。我不能100%确定我是否理解这个用例,但是您可以将回调限制为“返回(可能嵌套的)属性的内容”通过使用运行时不存在的幻象类型。大概是这样的:

  declare class DeepDooDoo {private dooDoo: true};
  type DeepVooDoo<T> = DeepDooDoo & (T extends object ? {
    [K in keyof T]: DeepVooDoo<T[K]>
  } : T)

  function getProperty<T, U>(obj: T, fn: (m: DeepVooDoo<T>)=>DeepVooDoo<U> ): void {
    console.log(fn(obj as DeepVooDoo<T>));
  }
就目前而言,看起来不错。幻影类型有点滥用类型系统,所以很可能会有奇怪的副作用。如果您决定继续这样做,请小心行事,确保它符合您的用例


好的,希望能有帮助。祝你好运

注意:
x.Address.Address2.State
只起作用,因为它是一个字符串,
fn
需要返回一个字符串(因为
keyof T
是一个字符串)。我对
getProperty(auth,x=>x.Address.Address2)感到困惑
只是just
x.Address.Address的更详细版本。Address 2
为什么不直接避免函数调用并使用Latter?这修复了警告,但没有回答问题,因为函数现在可以返回任何内容,而不仅仅是类型为T的对象的属性。例如,这将允许:getProperty(auth,x=>'hello'),这是不正确的iv'e添加了一个替代语法,希望这也能有所帮助。这样的语法有两个问题,第一个问题是您需要重载多达N个键,这意味着它只支持“finite”深度。第二个问题是,它要求键是字符串,这意味着你仍然无法使用函数语法并进行类型检查。是的,我想做一些事情,绕过类型脚本结构类型,转到“nominal”我在《编辑,好的解决方案》一书中提到了这一点。@jcalz我花了一整天的时间才明白你是怎么想出来的,但现在我知道了,感谢你的帮助:)
  declare class DeepDooDoo {private dooDoo: true};
  type DeepVooDoo<T> = DeepDooDoo & (T extends object ? {
    [K in keyof T]: DeepVooDoo<T[K]>
  } : T)

  function getProperty<T, U>(obj: T, fn: (m: DeepVooDoo<T>)=>DeepVooDoo<U> ): void {
    console.log(fn(obj as DeepVooDoo<T>));
  }
  getProperty(auth, x => x.Address.Address2); // okay
  getProperty(auth, x => "hello"); // error! string is not assignable to DeepDooDoo