简体   繁体   English

Typescript Generics keyof参数签名

[英]Typescript Generics keyof parameter signature

I'm stumped, hopefully this simplified example explains it well enough:我很难过,希望这个简化的例子能很好地解释它:

I have a class instance holding data, and another composite class instance to render the data.我有一个 class 实例保存数据,还有另一个复合 class 实例来呈现数据。 The data class gives callbacks to UI class in order to get and set data properties.数据 class 为 UI class 提供回调,以获取和设置数据属性。 I'm stumped on the "set" too but I'll stick to "getVal" for now.我也被“set”难住了,但我现在会坚持使用“getVal”。

class Person {
  private _data: DataObj

  constructor() {
    this._ui = new PersonUI({
      getVal: (key) => this.getVal(key)
    })
  }

  getVal<T extends keyof DataObj>( key: T ) {
    return this._data[key]
  }
}

class PersonUI {
  constructor(arg: UIArg) {}
}

Typescript can infer the type of the _data value, but I don't know how to write an interface for UIArg that will keep that inferred type, all I could come up with was "any" ex: Typescript 可以推断 _data 值的类型,但我不知道如何为 UIArg 编写一个接口来保持推断的类型,我能想到的只是“任何”例如:

interface UIArg {
  getVal: <T extends keyof DataObj>(key: T) => any
}

Is there a way to write the interface to keep the inferred type?有没有办法编写接口来保持推断的类型?

Bonus Q: is there a way to write the Person.p.setVal method to use the inferred type too?奖励问:有没有办法编写 Person.p.setVal 方法来使用推断类型? Ex:前任:

setVal<T extends keyof DataObj>(key: T, val: any) {
  this._data[key] = val
}

You're looking for indexed access types .您正在寻找索引访问类型 If you have a type T and a key type K extends keyof T , then the property at that key will have a value of type T[K] .如果您有一个类型T和一个键类型K extends keyof T ,那么该键的属性将具有类型T[K]的值。 In your case, DataObj is taking the role of T , and I will use K to represent the key type (which is more idiomatic than T )... so the value type in question is DataObj[K] :在您的情况下, DataObj扮演T的角色,我将使用K来表示键类型(比T更惯用)......所以有问题的值类型是DataObj[K]

interface UIArg {
    getVal: <K extends keyof DataObj>(key: K) => DataObj[K],
    setVal: <K extends keyof DataObj>(key: K, val: DataObj[K]) => void;
}

class Person {
    private _data: DataObj
    private _ui: PersonUI;
    constructor(data: DataObj) {
        this._data = data;
        this._ui = new PersonUI({
            getVal: key => this.getVal(key),
            setVal: (key, val) => this.setVal(key, val)
        })
    }

    getVal<K extends keyof DataObj>(key: K): DataObj[K] {
        return this._data[key]
    }

    setVal<K extends keyof DataObj>(key: K, val: DataObj[K]) {
        this._data[key] = val
    }

}

This compiles with no errors.这编译没有错误。

Playground link to code Playground 代码链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM