根据In TypeScript, how to get the keys of an object type whose values are of a given type? 的答案,我整理了这个工作示例,专门回答了您的问题(see playground),但困难的部分确实来自另一个答案。
type KeysMatching<T,V> = keyof { [ P in keyof T as T[P] extends V ? P : never ] : P };
function myFunction<T>(object: T, key: KeysMatching<T,string> ){
// ...
}
myFunction({keyA: "hello", keyB: 123}, "keyA") // OK
myFunction({keyA: "hello", keyB: 123}, "keyB") // error: `keyB` must be of type string but is number
我非常喜欢提取 PickValues<T,V> 类型的形式,它将 T 的属性过滤为仅具有 V 中的值的属性。然后只需在上面使用 keyof...
type PickValues<T,V> = { [ P in keyof T as T[P] extends V ? P : never ] : T[P] }
type Picked = PickValues<{keyA: "hello", keyB: 123},string>;
// type Picked = {
// keyA: "hello";
// }
//Your case
function myFunction<T>(object: T, key: keyof PickValues<T,string> ){
// ...
}
myFunction({keyA: "hello", keyB: 123}, "keyA") // OK
myFunction({keyA: "hello", keyB: 123}, "keyB") // error: `keyB` must be of type string but is number
顺便说一句,这个策略可以被推广到做相反的事情并创建一个OmitValues<T,V> 类型......
type OmitValues<T,V> = { [ P in keyof T as T[P] extends V ? never : P ] : T[P] }
type Omitted = OmitValues<{keyA: "hello", keyB: 123},string>;
// type Omitted = {
// keyB: 123;
// }
最后,它也可以重新用于仅提取具有可选性质的属性...
type OptionalValues<T> = { [ P in keyof T as undefined extends T[P] ? P : never ] : T[P] }
type Optional = OptionalValues<{keyA?: "hello", keyB: 123}>;
// type Optional = {
// keyA?: "hello" | undefined;
// }