我正在研究接受两个泛型类型参数的函数。其中一个是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'
。有什么办法可以实现我的目标?
答案 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")