我试图弄清楚如何正确键入一个 show
函数,该函数将接受一个对象 T
和一个键 K
,T[K]
可以保证实现了 toString()
方法。
这是我尝试使用映射类型
type ToStringablePropertyKeys<T> = keyof {
[K in keyof T]: { toString(): string }
}
function show<T, K extends ToStringablePropertyKeys<T>>(t: T, k: K): string {
return t[k].toString()
}
但是编译器说Property 'toString' does not exist on type 'T[K]'.
我在这里错过了什么?我如何说服 tsc
根据 toString
的定义,K
实际上存在?
答案 0 :(得分:5)
另一种方法:
function show<K extends string, T extends {[key in K]:{toString(): string}}>
(t: T, k: K ): string {
return t[k].toString()
}
答案 1 :(得分:2)
这是一个几乎理想的解决方案。尽管打字稿可以强制密钥仅是在 {toString():string}
上展开的密钥,但从那里推断出所有 T[k]
都将具有 toString():string
...
type ToStringable = { toString(): string };
type ToStringablePropertyKeys<T> = {
[k in keyof T]: T[k] extends ToStringable ? k : never
}[keyof T];
function show<T, K extends ToStringablePropertyKeys<T>>(t: T, k: K): string {
return (t[k] as any).toString(); // it seems typescript is not smart enough to infer that all t[k] will have toString
}
const testObject = {
string: 'test',
number: 123,
null: null,
undefined: undefined,
};
show(testObject, 'number');
show(testObject, 'string');
show(testObject, 'invalid-prop'); //this fails
show(testObject, 'null'); //this fails
show(testObject, 'undefined'); //this fails