获取 TypeScript 中泛型类型的特定键的类型
Get the type of a specific key of generic type in TypeScript
我正在努力从我正在构建的这个 updateArray
通用函数中获得复杂类型的功能:
// Updates an object array at the specified update key with the update value,
// if the specified test key matches the test value.
// Optionally pass testFailValue to set a default value if the test fails.
// Note that by passing a testFailValue ALL elements in the array will be updated at the specified update property.
// If it is omitted only elements passing the test will be updated.
export const updateArray = <T, U, V>(options: {
array: Array<T>
testKey: keyof T
testValue: U
updateKey: keyof T
updateValue: V
testFailValue?: V
}): Array<T> => {
const {
array,
testKey,
testValue,
updateKey,
updateValue,
testFailValue,
} = options
return array.map(item => {
if (item[testKey] === testValue) {
item[updateKey] = updateValue
} else if (testFailValue !== undefined) {
item[updateKey] = testFailValue
}
return item
})
}
TypeScript 会在 if 语句和两个赋值语句中抱怨,但在调用签名中,它不会抱怨,这正是我正在寻找的严格类型检查,例如:
interface IMyInterface {
propertyA: string
prepertyB: boolean
}
updateArray<IMyInterface, IMyInterface['propertyA'], IMyInterface['propertyB']>({
array: state.editors[editor].editorSettings,
testKey: "propertyA",
testValue: 'someValue',
updateKey: "propertyB",
updateValue: true,
testFailValue: false
})
如果我省略类型 U
和 V
,并将它们替换为 T[keyof T]
打字稿不会抱怨:
export const updateArray = <T>(options: {
array: Array<T>
testKey: keyof T
testValue: T[keyof T]
updateKey: keyof T
updateValue: T[keyof T]
testFailValue?: T[keyof T]
}): Array<T> => {
const {
array,
testKey,
testValue,
updateKey,
updateValue,
testFailValue,
} = options
return array.map(item => {
if (item[testKey] === testValue) {
item[updateKey] = updateValue
} else if (testFailValue !== undefined) {
item[updateKey] = testFailValue
}
return item
})
}
但这也不完全正确。 T[keyof T]
太灵活了:我可以将 'wrong' 类型分配给给定的 属性 (例如,在给定的示例中,一个布尔值到 属性 应该只拿着绳子,反之亦然)。显然,这种重新分配类型的行为在 JavaScript 中很好(这是 TypeScript 不会抱怨的原因之一),但对于我正在制作的这个函数来说是不需要的。我真正需要的是某种 typeof T[specific key]
,以确保 testValue
、updateValue
和 testFailValue
与正确的类型相对应,但 specific key
可以更改取决于 T
.
的实际类型
这样的事情能做吗?
您可以使用 extends
在 U
上添加约束,使其成为 T
的键的子集。 V
可以表示 updateKey
类型,也有相同的约束。
将您的问题简化为函数 updateObject
而不是 updateArray
它将变为:
function updateObject<
T,
U extends keyof T,
V extends keyof T,
>(
obj: T,
testKey: U,
testValue: T[U],
updateKey: V,
updateValue: T[V],
testFailValue?: T[V]
) {
if (obj[testKey] === testValue) {
obj[updateKey] = updateValue;
} else if (testFailValue !== undefined) {
obj[updateKey] = testFailValue;
}
}
updateObject({aString: 'hello', aNumber: 42}, 'aString', 'hello', 'aNumber', 23);
我正在努力从我正在构建的这个 updateArray
通用函数中获得复杂类型的功能:
// Updates an object array at the specified update key with the update value,
// if the specified test key matches the test value.
// Optionally pass testFailValue to set a default value if the test fails.
// Note that by passing a testFailValue ALL elements in the array will be updated at the specified update property.
// If it is omitted only elements passing the test will be updated.
export const updateArray = <T, U, V>(options: {
array: Array<T>
testKey: keyof T
testValue: U
updateKey: keyof T
updateValue: V
testFailValue?: V
}): Array<T> => {
const {
array,
testKey,
testValue,
updateKey,
updateValue,
testFailValue,
} = options
return array.map(item => {
if (item[testKey] === testValue) {
item[updateKey] = updateValue
} else if (testFailValue !== undefined) {
item[updateKey] = testFailValue
}
return item
})
}
TypeScript 会在 if 语句和两个赋值语句中抱怨,但在调用签名中,它不会抱怨,这正是我正在寻找的严格类型检查,例如:
interface IMyInterface {
propertyA: string
prepertyB: boolean
}
updateArray<IMyInterface, IMyInterface['propertyA'], IMyInterface['propertyB']>({
array: state.editors[editor].editorSettings,
testKey: "propertyA",
testValue: 'someValue',
updateKey: "propertyB",
updateValue: true,
testFailValue: false
})
如果我省略类型 U
和 V
,并将它们替换为 T[keyof T]
打字稿不会抱怨:
export const updateArray = <T>(options: {
array: Array<T>
testKey: keyof T
testValue: T[keyof T]
updateKey: keyof T
updateValue: T[keyof T]
testFailValue?: T[keyof T]
}): Array<T> => {
const {
array,
testKey,
testValue,
updateKey,
updateValue,
testFailValue,
} = options
return array.map(item => {
if (item[testKey] === testValue) {
item[updateKey] = updateValue
} else if (testFailValue !== undefined) {
item[updateKey] = testFailValue
}
return item
})
}
但这也不完全正确。 T[keyof T]
太灵活了:我可以将 'wrong' 类型分配给给定的 属性 (例如,在给定的示例中,一个布尔值到 属性 应该只拿着绳子,反之亦然)。显然,这种重新分配类型的行为在 JavaScript 中很好(这是 TypeScript 不会抱怨的原因之一),但对于我正在制作的这个函数来说是不需要的。我真正需要的是某种 typeof T[specific key]
,以确保 testValue
、updateValue
和 testFailValue
与正确的类型相对应,但 specific key
可以更改取决于 T
.
这样的事情能做吗?
您可以使用 extends
在 U
上添加约束,使其成为 T
的键的子集。 V
可以表示 updateKey
类型,也有相同的约束。
将您的问题简化为函数 updateObject
而不是 updateArray
它将变为:
function updateObject<
T,
U extends keyof T,
V extends keyof T,
>(
obj: T,
testKey: U,
testValue: T[U],
updateKey: V,
updateValue: T[V],
testFailValue?: T[V]
) {
if (obj[testKey] === testValue) {
obj[updateKey] = updateValue;
} else if (testFailValue !== undefined) {
obj[updateKey] = testFailValue;
}
}
updateObject({aString: 'hello', aNumber: 42}, 'aString', 'hello', 'aNumber', 23);