是否有办法进行下列类型检查?
function getNumberFromObject<T>(obj: T, key: keyof T): number {
return obj[key] // ERROR: obj[key] might not be a number
}我希望指定key不仅应该是T的一个键,而且应该是一个具有number值的键。
发布于 2018-09-05 15:46:49
要使调用方和getNumberFromObject<T>类型检查的实现都正确,最简单的方法是:
function getNumberFromObject<T extends Record<K, number>, K extends keyof any>(
obj: T,
key: K
): number {
return obj[key] // okay
}当你称之为:
getNumberFromObject({dog: 2, cat: "hey", moose: 24}, "dog"); // okay
getNumberFromObject({dog: 2, cat: "hey", moose: 24}, "cat"); // error
getNumberFromObject({dog: 2, cat: "hey", moose: 24}, "moose"); // okay
getNumberFromObject({dog: 2, cat: "hey", moose: 24}, "squirrel"); // error这一切都运行得很好,除了您得到的错误有点模糊,因为它抱怨Object literal may only specify known properties, and 'dog' does not exist in type 'Record<"somebadkey", number>'。这个抱怨是一个超额财产检查,并不是真正的问题。
如果要使调用方获得更好的错误,可以使用更复杂的条件类型:
function getNumberFromObject<T, K extends keyof any & {
[K in keyof T]: T[K] extends number ? K : never
}[keyof T]>(
obj: T,
key: K
): T[K] {
return obj[key] // okay
}
getNumberFromObject({ dog: 2, cat: "hey", moose: 24 }, "dog"); // okay
getNumberFromObject({ dog: 2, cat: "hey", moose: 24 }, "cat"); // error
getNumberFromObject({ dog: 2, cat: "hey", moose: 24 }, "moose"); // okay
getNumberFromObject({ dog: 2, cat: "hey", moose: 24 }, "squirrel"); // error在这种情况下,T是不受约束的,但是K只能是来自T ( T[K]是number )的键。
现在,错误说,Argument of type '"somebadkey"' is not assignable to parameter of type '"dog" | "moose"'.,这是更有利于开发人员。不过,不确定签名的额外复杂性是否值得您这么做。
希望这能有所帮助。祝好运!
Update:后一个函数返回T[K],而不是number。这可能是件好事,因为T[K]可能比number更具体。例如:
interface Car {
make: string,
model: string,
horsepower: number,
wheels: 4
}
declare const car: Car;
const four = getNumberFromObject(car, 'wheels'); // 4, not number值four的类型是4,它比number更具体。如果您真的想将函数的返回类型扩展到number,您可以.尽管实现会对此犹豫不决,因为编译器不够聪明,无法意识到在一般情况下T[K]是可以分配给number的。有处理这些问题的方法,但最简单的方法是在实现中使用类型断言(return obj[key] as any as number)。
发布于 2021-10-01 13:57:04
最佳解决方案:
const getNumberFromObject = <T extends Record<K, number>, K extends keyof T>(
obj: T,
key: K,
) => {
return obj[key];
};https://stackoverflow.com/questions/52188399
复制相似问题