具有特定键和值的泛型类型

时间:2020-03-17 18:22:56

标签: typescript typescript-generics

我正在研究接受两个泛型类型参数的函数。其中一个是Object类型,另一个是扩展了传递对象类型keyof的字符串。我需要以某种方式确定所提供的Object必须包含第二个参数中提供的键,并且它的值也应该是指定的类型。

我尝试过这样的事情:

const someFn = <
  T extends {[key: string]: number | null},
  K extends keyof T
>(data: T[], dataField: K) => {

  // expecting data values to be (number | null)[] for further purposes
  const dataValues = data.map(datum => datum[dataField]);

}

上面的代码仅在传递的对象中的所有键均为number | null

时有效
type WorkingType = { value: number | null }
const workingArray = [{value: 1}, {value: null}]

someFn<WorkingType, "value">(workingArray, "value") // this works just fine

但是如果包含不同类型字段的对象出现错误:

type FailingType = { value: number | null, sthElse: string }
const workingArray = [{value: 1, sthElse: ""}, {value: null, sthElse}]

//. Property 'sthElse' is incompatible with index signature.
//   Type 'string' is not assignable to type 'number | null'
someFn<FailingType, "value">(workingArray, "value") 

因此,我需要做的是提供某种信息,即仅提供K的密钥才需要number | null,我尝试过以下操作:

const someFn<
  T extends { [key: T]: number | null },
  K extends keyof T
>(data: T[], dataKey: K) => {/* ... */}

但是TS似乎不允许这样做,我得到了An index signature parameter type must be either 'string' or 'number'。有什么办法可以实现我的目标?

1 个答案:

答案 0 :(得分:0)

我希望我明白你的意思,无论如何这对我有用:

    interface someFnI {
    <T,K extends keyof T>(data: T[], dataField: K);
}



const someFn = <
    T,
    K extends keyof T
>(data: T[], dataField: K) => {

    // expecting data values to be (number | null)[] for further purposes
const dataValues: T[K][] = data.map(datum => {
    return datum[dataField]});
    console.log(dataValues);

}

let myIdentity: someFnI = someFn;


type NotFailingType = { value: number | null, sthElse: string }
const workingArray = [
    { value: 1, sthElse: "" }, 
    { value: null, sthElse: null },
    //this will break as expected : uncomment below to check
    // { value: "notallowed", sthElse: null }
]

//. Property 'sthElse' is incompatible with index signature.
//   Type 'string' is not assignable to type 'number | null'
myIdentity<NotFailingType, "value">(workingArray, "value")



type WorkingType = { value: number | null }
const workingArray2 = [{ value: 1 }, { value: null }]

myIdentity<WorkingType, "value">(workingArray2, "value")